gpt4 book ai didi

java - 如何使用 JUnit 或 Mockito 测试匿名方法?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:37:28 25 4
gpt4 key购买 nike

我有简单的类,但有匿名代码块。我需要用测试覆盖这门课。

public class CleanerTask {

private final Logger log = LoggerFactory.getLogger(getClass());
DataWarehouseMessageDao dwMessageDao;
int cleanerDelay = 0;
TransactionTemplate template;

public CleanerTask(DataWarehouseMessageDao dwMessageDao, int cleanerDelay, TransactionTemplate template) {
this.dwMessageDao = dwMessageDao;
this.cleanerDelay = cleanerDelay;
this.template = template;
}

public void clean() {
log.info("Cleaner started");
final Date olderThan = new Date();
olderThan.setDate(olderThan.getDate() + cleanerDelay);
template.execute(new TransactionCallback<Date>() {
@Override
public Date doInTransaction(TransactionStatus transactionStatus) {
dwMessageDao.deleteAllByStatusAndDate(DataWarehouseMessageStatus.SAVED.getValue(), olderThan);
return olderThan;
}
});
}
}

并测试:

@RunWith(MockitoJUnitRunner.class)
public class CleanerTaskTest {

final static int CLEANER_DELAY = 5;

@Mock
DataWarehouseMessageDao dao;

@Mock
TransactionTemplate template;

CleanerTask cleanerTask;

@Before
public void setUp() throws Exception {
cleanerTask = new CleanerTask(dao, CLEANER_DELAY, template);
}

@Test
public void successfulScenario() {
try {
cleanerTask.clean();
verify(template, times(1)).execute(isA(TransactionCallback.class));
//that verify was not triggered
//verify(dao, times(1)).deleteAllByStatusAndDate(anyInt(), isA(Date.class));
} catch (Exception e) {
e.printStackTrace();
fail("No exceptions must occur");
}
}
}

Commented line doesn't work. Log: Wanted but not invoked: dao.deleteAllByStatusAndDate( , isA(java.util.Date) ); -> at com.nxsystems.dw.publisher.handler.CleanerTaskTest.successfulScenario(CleanerTaskTest.java:52) Actually, there were zero interactions with this mock.

at com.nxsystems.dw.publisher.handler.CleanerTaskTest.successfulScenario(CleanerTaskTest.java:52) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:62)

此外,当此 tets 启动时,调试器不会进入匿名 block 。那么如何让 Mockito 进入匿名 block 呢?

最佳答案

为什么不起作用

你的问题是你测试中的 TransactionTemplate 是一个模拟。因此,它具有与 TransactionTemplate 相同的接口(interface),但它不知道如何操作。你负责它的实现——这就是模拟的全部意义所在。您在代码中明确调用了 template.execute(),这就是您的第一次验证通过的原因。但是 execute() 不是来自 Spring 的(或者更准确地说,您测试中的 template 不是 Spring 的 TransactionTemplate 的实例,它只是它的一个模拟)- 好吧,我们可以说它是“空的”,因为它是在模拟上调用的,而您没有告诉模拟如何调用 execute()它应该表现良好。

我将如何修复它

在这种情况下,我真的不鼓励您进行此类单元测试,因为您正在此处测试实现。至少在我看来,您应该测试的是功能,意思是给定某些条件,事情发生时然后 应该会出现一些结果。这将需要将其更改为集成测试(使用 DBUnit 或其他任何东西)并断言您是否确实删除了应该删除的内容。我的意思是您真正关心的是什么 - 知道某些方法已被调用或您希望的事情实际发生了吗?

你怎么能,但恕我直言不应该,修复它。

但是如果您真的想要测试那段匿名代码,那么我会简单地将它(整个匿名类)提取到一个单独的类中,然后只为那个新类编写一个单元测试等等正是因为它的 doInTransaction() 方法。在这种情况下,您将使用 new 创建它,在其中设置模拟 DataWarehouseMessageDao 并简单地执行您的 verify()

关于java - 如何使用 JUnit 或 Mockito 测试匿名方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11962584/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com