How do I do a contains allOf assertion on a Java Map?
The following did not work
val testMap = new java.util.LinkedHashMap[Int, Int]()
testMap.put(1,2)
testMap.put(2,4)
testMap.put(3,6)
testMap should contain allOf (1->2, 2->4, 3->6)
it gives
{1=2, 2=4, 3=6} did not contain all of ((1,2), (2,4), (3,6))
The docs say
The Aggregating companion object provides implicit instances of Aggregating[L] for types GenTraversable[E], java.util.Collection[E], java.util.Map[K, V], String, Array[E].
— http://www.scalatest.org/user_guide/using_matchers#workingWithAggregations
What am I doing wrong?
Scala v2.11
ScalaTest v3.1.1
Alternatively consider CollectionConverters
import scala.jdk.CollectionConverters._
testMap.asScala should contain allOf (1->2, 2->4, 3->6)
If we wish to maintain the following DSL
testMap should contain allOf (1->2, 2->4, 3->6)
then we could provide a custom instance of Aggregating
typeclass which compares equality of Entry
with Scala tuples
trait JavaMapHelpers {
def javaEntryEqualsScalaTuple[K, V]: Equality[java.util.Map.Entry[K, V]] =
(a: java.util.Map.Entry[K, V], b: Any) => b match {
case (k, v) => a.getKey == k && a.getValue == v
case _ => false
}
implicit def aggregatingNatureOfJavaMapWithScalaTuples[K, V, JMAP[k, v] <: java.util.Map[k, v]]: Aggregating[JMAP[K, V]] =
Aggregating.aggregatingNatureOfJavaMap(javaEntryEqualsScalaTuple)
def javaMap[K, V](elements: (K, V)*): java.util.LinkedHashMap[K, V] = {
val m = new java.util.LinkedHashMap[K, V]
elements.foreach(e => m.put(e._1, e._2))
m
}
}
class JavaMapSpec extends AnyFlatSpec with Matchers with JavaMapHelpers {
"Java Map" should "be checkable with Scala tuples" in {
javaMap((1,2), (2,4), (3,6)) should contain allOf (1->2, 2->4, 3->6)
}
}
Defining custom equality which compares Java Entry
with Scala tuple works because under the hood containsAllOf
calls entrySet
on Java map and then checks with provided Equality
def containsAllOf(map: JMAP[K, V], elements: scala.collection.Seq[Any]): Boolean = {
checkAllOf(map.entrySet.asScala, elements, equality)
}
One difference to note between the syntax supported on Java and Scala collections is that in Java, Map is not a subtype of Collection, and does not actually define an element type. You can ask a Java Map for an "entry set" via the entrySet method, which will return the Map's key/value pairs wrapped in a set of java.util.Map.Entry, but a Map is not actually a collection of Entry. To make Java Maps easier to work with, however, ScalaTest matchers allows you to treat a Java Map as a collection of Entry, and defines a convenience implementation of java.util.Map.Entry in org.scalatest.Entry. — http://www.scalatest.org/user_guide/using_matchers#javaCollectionsAndMaps
Try:
val testMap = new java.util.LinkedHashMap[Int, Int]()
testMap.put(1,2)
testMap.put(2,4)
testMap.put(3,6)
testMap should contain allOf (Entry(1, 2), Entry(2, 4), Entry(3, 6))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With