'должен содержать allOf' на java .util.Map? - PullRequest
3 голосов
/ 09 мая 2020

Как мне сделать утверждение содержит allOf на карте Java?

Следующее не сработало

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)

дает

{1=2, 2=4, 3=6} did not contain all of ((1,2), (2,4), (3,6))

документы говорят:

Сопутствующий объект Aggregating предоставляет неявные экземпляры Aggregating [L] для типов GenTraversable [E], java .util.Collection [E], java .util.Map [K , V], String, Array [E].

- http://www.scalatest.org/user_guide/using_matchers#workingWithAggregations

Что я делаю не так?

Scala     v2.11
ScalaTest v3.1.1

Ответы [ 2 ]

3 голосов
/ 09 мая 2020

В качестве альтернативы рассмотрите Конвертеры коллекции

import scala.jdk.CollectionConverters._
testMap.asScala should contain allOf (1->2, 2->4, 3->6)

Если мы будем sh поддерживать следующий DSL

testMap should contain allOf (1->2, 2->4, 3->6)

, тогда мы можем предоставить пользовательский экземпляр Aggregating класса типов, который сравнивает равенство Entry с Scala кортежами

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)
  }
}

Определение пользовательского равенства, которое сравнивает Java Entry с Scala кортеж работает потому что под капотом containsAllOf вызывает entrySet на карте Java, а затем проверяет с предоставленным Equality

def containsAllOf(map: JMAP[K, V], elements: scala.collection.Seq[Any]): Boolean = {
  checkAllOf(map.entrySet.asScala, elements, equality)
}
3 голосов
/ 09 мая 2020

Следует отметить одно различие между синтаксисом, поддерживаемым в коллекциях Java и Scala, заключается в том, что в Java Map не является подтипом Collection и фактически не определяет тип элемента. Вы можете запросить у карты Java «набор записей» с помощью метода entrySet, который вернет пары ключ / значение карты, заключенные в набор java .util.Map.Entry, но Map на самом деле не является сборник Entry. Однако, чтобы упростить работу с картами Java, сопоставители ScalaTest позволяют обрабатывать карту Java как коллекцию Entry и определяют удобную реализацию java .util.Map.Entry в org.scalatest. Вход. - http://www.scalatest.org/user_guide/using_matchers#javaCollectionsAndMaps

Попробуйте:

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))
...