Elastic4s,mockito和验证类型擦除和implicits

时间:2015-06-10 17:31:32

标签: scala mockito elastic4s

在以前的Elastic4s版本中,您可以执行类似

的操作
val argument1: ArgumentCapture[DeleteIndexDefinition] = ???
verify(client).execute(argument1.capture())
assert(argument1 == ???)

val argument2: ArgumentCapture[IndexDefinition] = ???
verify(client, times(2)).execute(argument2.capture())
assert(argument2 == ???)

在您的测试中多次执行后(即一个DeleteIndexDefinition,然后是两个IndexDefinition)。并且每个验证将与其类型匹配。

但是,Elastic4s现在在其client.execute方法中采用隐式参数。该参数的类型为Executable[T,R],这意味着您现在需要类似

的内容
val argument1: ArgumentCapture[DeleteIndexDefinition] = ???
verify(client).execute(argument1.capture())(any[Executable[DeleteIndexDefinition,R]])
assert(argument1 == ???)

val argument2: ArgumentCapture[IndexDefinition] = ???
verify(client, times(2)).execute(argument2.capture())(any[Executable[IndexDefinition,R]])
assert(argument2 == ???)

这样做之后,我收到了一个错误。 Mockito在第一次验证中考虑了三个client.execute。是的,即使第一个参数属于不同的类型。

这是因为隐式(第二个参数)在类型擦除后具有相同的类型Executable

因此论文失败了。如何在此设置中进行测试?

2 个答案:

答案 0 :(得分:1)

我的解决方案是使用泛型类型创建一个验证。我花了一段时间才意识到,即使没有普通类型,你总是有AnyRef。

所以,这样的工作

val objs: ArgumentCaptor[AnyRef] = ArgumentCaptor.forClass(classOf[AnyRef])
verify(client, times(3)).execute(objs.capture())(any())
val values = objs.getAllValues
assert(values.get(0).isInstanceOf[DeleteIndexDefinition])
assert(values.get(1).isInstanceOf[IndexDefinition])
assert(values.get(2).isInstanceOf[IndexDefinition])

我创造了问题和答案。但我会考虑其他答案。

答案 1 :(得分:1)

现在采用elastic4s来封装执行每个请求类型的逻辑的方法是使用typeclasses的方法。这就是隐含现在存在的原因。它有助于模块化每个请求类型,并避免开始进入ElasticClient类的God类反模式。

我能想到的两件事可能会对你有所帮助:

  1. 你已经发布了什么,使用Mockito并传入隐含的另一个匹配器。这就是你通常使用implicits模拟方法的方法。

  2. 不使用mockito,而是假脱机本地嵌入式节点,并针对实际数据进行尝试。当我编写elasticsearch代码时,这是我的首选方法。优点是您正在测试真实服务器的真实查询,因此不仅检查它们是否被调用,而且它们实际上是有效的。 (有些人可能会认为这是一个集成测试,但无论我不同意,它都在一个自包含的测试中运行,没有外部deps)。

  3. 最新版本的elastic4s甚至包括testkit,这使得获取嵌入式节点非常容易。您几乎可以查看任何单元测试,以了解如何使用它。