首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在带有Spec2的Scala中使用Mockito

在带有Spec2的Scala中使用Mockito
EN

Stack Overflow用户
提问于 2015-02-27 05:39:48
回答 1查看 266关注 0票数 1

这是在Play框架的上下文中。我有一个实例化验证器的控制器。验证器具有验证方法。控制器有一个putEnity()方法,该方法使用这个validate()来验证它接收到的有效负载。

为了对控制器进行单元测试,我想模拟调用Validator.validate()。TestController看起来像这样

代码语言:javascript
复制
class EntityControllerTest extends FlatSpec with Mockito {
def testPutEntity() = {
  val payload = createPayload()
  val mockValidator = mock[Validator]
  when(mockValidator.validate(anyString, anyString)).thenReturn(EntityValidationResult(true, "Test"))                                            
  EntityController.putEntity(payload)
}

问题是,这个模拟调用没有被使用,但实际的validate()被调用了,因此测试失败。

我该如何解决这个问题呢?

EN

回答 1

Stack Overflow用户

发布于 2015-02-27 08:56:41

问题是在你的最后一行:

代码语言:javascript
复制
EntityController.putEntity(payload)

您实际上是在调用EntityController上的静态方法,尽管您试图配置一个模拟Validator,但您从未有机会将其“注入”到控制器中。

在不了解如何实现控制器的情况下提出一个理想的解决方案可能有点困难,但在猜测中,您可能希望执行以下操作,以允许注入模拟的Validator进行测试,但其他一切都能像以前一样工作。

我将逐步介绍它(希望)让它更清楚:

第1步-使EntityController可实例化:

你可能已经得到了类似这样的东西:

代码语言:javascript
复制
object EntityController extends Controller {
   ...
   def putEntity = Action ...
   ..
}

将其替换为:

代码语言:javascript
复制
class EntityControl extends Controller {
   ...
   def putEntity = Action ...
   ...
}

object EntityController extends EntityControl

现在你已经给自己提供了使用与你的“生产”对象相同行为的new的能力。但我们需要能够在模拟验证器中替换...

步骤2-在您的EntityControl中需要一个验证器实例

您的旧EntityController对象可能具有以下内容:

代码语言:javascript
复制
object EntityController extends Controller {
  val validator = new Validator(...)
  ...
}

这就是为什么你永远不能让你的模拟验证器参与进来的原因。让我们将它作为构造函数参数注入,这样它就不会被遗忘:

代码语言:javascript
复制
class EntityControl(val validator:Validator) extends Controller {
   ...
}

object EntityController extends EntityControl(new Validator(...))

因此,我们的“生产”EntityController对象具有我们过去拥有的所有功能,但关键的区别是我们公开了一个"testing seam",允许在需要时注入一个模拟。

第3步-注入,然后测试!

切换到您的测试规范,并设置一个可测试的EntityControl实例

代码语言:javascript
复制
class EntityControllerTest extends FlatSpec with Mockito {

  def testPutEntity() = {
    val payload = createPayload()
    val mockValidator = mock[Validator]
    when(mockValidator.validate(anyString, anyString)).thenReturn(EntityValidationResult(true, "Test"))  

    val myTestableEC = new EntityControl(mockValidator)                                          
    myTestableEC.putEntity(payload)
}

随着您开发更多的测试用例,您可能希望将测试的设置和连接部分提取到一个合适的函数中,甚至是一个Specs2 Scope中。

希望这篇文章能对你有所帮助,并为你阐明一些有效的单元测试思想。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28753267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档