ksceriath
ksceriath

Reputation: 195

ScalaMock : expect a Double within some tolerance

I am using a MockFunction1, expecting an argument and expecting it to be called once.

mockFunction.expects(result).once()

The type of result object contains several values of type Double.

I want the expected result object to match the actual within some tolerance limits. (For example, if the actual object contains a value 10.742345, I want the expected object with value 10.74 to match).

How can I achieve this?

Edit: The type of result object is of the form:

class Result {
 ...
  m: Metrics,
 ...
}
class Metrics {
 ...
  a: Double,
  b: Double,
 ...

}

Upvotes: 0

Views: 332

Answers (2)

ksceriath
ksceriath

Reputation: 195

Appears there is no built in mechanism in scalamock to give a default comparator for comparing all instances of a type.

To work around this, I ended up using 'argument capture' and writing a custom comparator for the entire object:

val actualResult = CaptureOne[Result]()
mockFunction expects capture(actualResult) once
....
actualResult.value.shouldEqual(result)(EqualityWithTolerance)

Upvotes: 0

Boris Azanov
Boris Azanov

Reputation: 4491

You can do it using where as custom matcher:

import org.scalamock.scalatest.MockFactory
import org.scalamock.function.FunctionAdapter1

case class Foo(d: Double, otherField: String)

trait Service {
  def f(p: Foo): String = s"call f on $p"
}

// add function to construct custom matchers:
def toTolerantMatcher(expected: Foo): FunctionAdapter1[Foo, Boolean] =
  where {
    (actual: Foo) => (~expected.d).equals(actual.d) && expected.otherField == actual.otherField
  }

// and use it in your test:
val service = mock[Service]
val expected = Foo(0.0004, "example")
(service.f _).expects(toTolerantMatcher(expected)).once()
val actual = Foo(0.0003, "example")
service.f(actual)

inside toTolarantMatcher unary operator ~ makes comparing d field with tolerance (from org.scalamock.matchers):

object MatchEpsilon {

  val epsilon = 0.001
}

Upvotes: 1

Related Questions