Reputation: 26598
I have
case class Foo(field1: String, field2: String, field3: String)
expected: Seq[Foo] = Seq(...)
result: Seq[Foo] = Seq(...)
I want to write a Scala matcher that compare the elements of Seq without taking in consideration field1.
So two elements will match if field2 and field3 are equals. Field1 value is not considerated.
Example:
val expected = Seq(
Foo(
"f1", "f2", "f3"
)
)
val result = Seq(
Foo(
"fx", "f2", "f3"
)
)
This two sequence has to match.
result should matchWithoutId(expected)
Upvotes: 0
Views: 1957
Reputation: 170815
The documentation is in Using custom Matchers, this example would be (for example)
def matchWithoutId(expected: Foo): Matcher[Foo] = Matcher { actual =>
MatchResult(
actual.field2 == expected.field2 && actual.field3 == expected.field3,
if (actual.field2 != expected.field2)
s"field2 of $actual was not equal to that of $expected"
else
s"field3 of $actual was not equal to that of $expected",
s"field2 and field3 of $actual were equal to those of $expected")
}
Adjust error messages to taste.
Or another approach (probably a better one in this case):
def matchWithoutId(expected: Foo): Matcher[Foo] = have(
'field2 (expected.field2),
'field3 (expected.field3)
)
Normally I'd say using Symbols to name properties and use reflection should be avoided, but here a change to Foo
will make the tests fail to compile anyway because of access to expected
's fields.
EDIT: I missed that you want to compare Seq[Foo]
s and not Foo
s, so Mario Galic's answer is probably the one you want. Still, this can hopefully be useful as well.
Upvotes: 3
Reputation: 48420
Working with "sequences" states
if you want to change how containership is determined for an element type E, place an implicit
Equality[E]
in scope or use the explicitly DSL.
so the following should work
(expected should contain theSameElementsAs (result)) (decided by fooEqualityWithoutId)
Note about contains
usage
Note that when you use the explicitly DSL with
contain
you need to wrap the entire contain expression in parentheses
Here is the full example
import org.scalactic._
import org.scalatest._
import org.scalatest.matchers.should.Matchers
import org.scalactic.Explicitly._
class CustomizeEqualitySeqSpec extends FlatSpec with Matchers with Explicitly {
case class Foo(field1: String, field2: String, field3: String)
val expected = Seq(Foo("f1", "f2", "f3"))
val result = Seq(Foo("fx", "f2", "f3"))
val fooEqualityWithoutId = new Equality[Foo] {
override def areEqual(a: Foo, b: Any): Boolean = b match {
case Foo(_, field2, field3) => a.field2 == field2 && a.field3 == field3;
case _ => false
}
}
"Sequences" should "use custom Equality[E]" in {
(expected should contain theSameElementsAs (result)) (decided by fooEqualityWithoutId)
}
}
Upvotes: 2