调用更改mockito中的模拟对象

Tom*_*han 5 unit-testing mockito

我有一个非常复杂的方法,我想测试其行为(使用 Mockito 和 JUnit)。该方法将一个对象(我们称之为它的 type State)作为输入,并且应该考虑一些不同的状态变量来决定其输出。

作为示例,考虑以下规范(s是该类的模拟State):

  1. 如果s.varOne已设置,则返回其值。
  2. 否则,如果s.varTwo已设置,则返回该值。
  3. 否则,如果s.varThree已设置,则调用s.update(s.varThree)然后 return s.varOne,该值现在将具有一个值(即使在第 1 阶段没有)。
  4. 否则,抛出错误。

为了正确测试案例 3,我想设置该s对象,以便s.varOnes.varTwo都一开始就未设置,但如果(且仅当!) sut 调用s.update(s.varThree),然后s.varOne返回一些内容。

在 Mockito 中是否有设置此行为的好方法?

我考虑过为 建立一些返回值链s.varOne,然后验证调用的顺序是否与输出的顺序相对应(当然,sut 的返回值也是正确的),但这感觉很脏; 如果我随后更改方法以其他方式计算其返回值,即调用s.varOne不同次数但不更改其输出,那么即使功能相同,测试也会失败。

我理想的解决方案是一种可以为模拟对象添加一些“延迟”设置的方法,该设置在 sut 调用该s.update()方法时运行,但我无法找到实现该目标的方法。

Jef*_*ica 4

您有几个选项可以在这里模拟状态更改,一个好的选项和一个更好的选项。正如上面tieTYT所指出的,最好的选择就是解开 的一般契约:可变以及拥有不是简单 setter 的自变异方法State真的有意义吗?State

\n\n

好的选择(有时)是创建一个一次性子类\xe2\x80\x94,或者更好的是,创建一个接口实现\xe2\x80\x94of State

\n\n
@Test public void yourTest() {\n  SystemUnderTest sut = createSystemUnderTest();\n  State state = new State() {\n    @Override public void update() {\n      this.varOne = 42;\n    }\n  }\n  // rest of your test\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

到那时,您可能根本不需要 Mockito。但请注意:如果 State 有副作用或难以实例化,这可能会变得有点棘手。您可以提取一个接口,这需要您将字段包装在 getter 中;您还可以将 State 设为一个命名抽象类,然后传递mock(MyAbstractState.class, CALLS_REAL_METHODS),但是当您考虑到没有初始化程序实际在该假实例上运行,因此字段全部为零或 null 时,这会变得特别棘手。如果这并不简单,就不要浪费时间将方钉强行插入圆孔中。

\n\n

模拟的一种更常见的模式是使用自定义Answer,您可以在其中执行任意代码,但会牺牲类型安全性。这是一个示例,假设update是 void 并且varThree是整数:

\n\n
@Test public void yourTest() {\n  SystemUnderTest sut = createSystemUnderTest();\n  final State s = Mockito.mock(State.class);\n  doAnswer(new Answer<Void>() {\n    @Override public Void answer(InvocationOnMock invocation) {\n      int actualVarThree = (int) invocation.getArguments()[0];\n      assertEquals(EXPECTED_VAR_THREE, actualVarThree);\n      s.varOne = actualVarThree;\n      return null;\n    }\n  }).when(s).update(anyInt());\n  // rest of your test\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,参数数组是一个Object[],因此强制转换是必要的并且有点危险,但是当您的模拟方法被调用时,您可以同步进行各种断言和修改。

\n\n

希望有帮助!

\n