【问题标题】:Why doesn't Mockito's when() get triggered?为什么 Mockito 的 when() 没有被触发?
【发布时间】:2012-04-09 13:17:07
【问题描述】:

我需要测试一个服务类,但是当我尝试模拟 dao 类时,它没有被触发,因此无法使用 ThenReturn()。

我认为问题在于我在服务类(Spring MVC 3.1)中为我的 Dao 和 @Autowired 使用了一个接口:

界面:

public interface TestDao {
    int createObject(Test test) throws NamingException;
}

实现:

@Repository
public class TestDaoImpl implements TestDao {

    @Override
    public int createObject(Test test) {
        KeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcTemplate.update(new InsertNewTest(test), keyHolder);
        return ((java.math.BigDecimal)keyHolder.getKey()).intValue();
    }
}

服务:

public class RegTest {
    @Autowired
    TestDao testDao;

    public int regTest(int .....) {
        .
        .
        int cabotageId = testDao.createObject(test);
    }
}

在测试中我有:

@RunWith(MockitoJUnitRunner.class)
public class TestRegService {
    @InjectMocks
    private RegTest regTest = new RegTest();

    @Mock
    TestDao testDao;

    @Test()
    public void test() {
        .
        when(testDao.createObject(null)).thenReturn(100);
        .
    }

testDao.createObject(null) 返回 0(由于被模拟)而不是 100,因为我试图实现。

有人可以帮忙吗?

问题解决了!

传递给 createObject() 的测试对象不匹配。使用

testDao.createObject(any(Test.class))

成功了!

【问题讨论】:

  • 我试图重现您的问题,但是当我这样做时,我得到了适当的返回值。您如何检查 createObject 的结果?你可以在你的when 电话之后,简单地System.out.println(testDao.createObject(null)) 看看它说了什么。如果它说 100,那么你就知道问题出在测试上,而不是模拟上。如果它说 0,那么它是 Mockito 的某种错误。
  • 嗯...它说 0 :-( 在将其报告为错误之前,我会尝试其他建议...

标签: spring unit-testing mocking mockito


【解决方案1】:

如果您的测试实际上将值传递给 createObject,则 when(testDao.createObject(null)... 永远不会匹配。您可以将Test 的任何实例与testDao.createObject(any(Test.class)) 匹配,而不是匹配null...

此外,当您稍后尝试提供 new Test() 作为要匹配的参数时,它实际上会尝试匹配 Test 的确切实例,但可能您的真实代码正在新建一个不同的实例。所以使用Matchers.any(Test.class)作为参数来匹配是要走的路。

【讨论】:

    【解决方案2】:

    Mockito 注入机制不了解 Spring @Autowired 或 CDI @Inject 注解。它只是尝试根据模拟的类型和名称找到最佳候选者,并且它也可以查找私有字段。参见@InjectMocks 的javadoc:http://docs.mockito.googlecode.com/hg/1.9.0/org/mockito/InjectMocks.html

    您使用的语义是正确的,但如果您遇到问题,我宁愿寻找不正确的交互或不正确的参数。

    你确定regTest.regTest(int...) 中的test 变量在传递给testDao.createObject(test) 时真的是null 吗?

    【讨论】:

    • 不,它是一个 Test() 对象。我试图为它提供new Test() 而不是null,但结果相同
    • 如果您的测试实际上传递了一个值,那么when(testDao.createObject(null)... 永远不会匹配。您可以将任何 Test 实例与 testDao.createObject(any(Test.class))... 匹配,而不是匹配 null
    • Kevin,any() 匹配器成功了。请创建一个答案,如果你愿意,我会接受你的:-)
    【解决方案3】:

    我不知道这是否是示例中的拼写错误,但您有 RegTest.regTest() 调用 createTest() 而不是 createObject()。否则,我不认为 @Autowired 与它有任何关系,因为您的测试本身没有在具有 Spring 管理的容器中运行。如果不是拼写错误,并且 createTest 实际上是与 createObject 不同的真实方法,那么 Mockito 中模拟对象的默认行为是为数字返回类型返回适当类型的零。

    【讨论】:

      【解决方案4】:

      我认为你对自动接线没有被调用是正确的。您可以使用 setTestDao() 调用自己注入 dao。 Mockito 还支持spy,它允许您跟踪对象代码并仅替换函数。

      【讨论】:

      • 我对 Spring MVC 和 Mockito 还很陌生,因此非常感谢有关注入或使用 @Spy 的一点帮助!
      • Autowire 告诉 Spring 寻找 TestDao 的配置并将 RegTest 设置为该对象。但是单元测试不使用 Sprint,因此 testDao 永远不会设置为对象。您可以自己设置测试以获得 TestDao。您可能想在StackOverflowWikipedia 上查找反向依赖注入
      猜你喜欢
      • 2021-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多