我的 Utils 类有一个依赖于外部资源(例如数据库连接)的 init 方法,我无法使用 Mockito 模拟该方法。 Utils 似乎可以在我的应用程序实例之间共享,因此在
中声明为静态(即类变量)public class EmailNotificationWorkItemHandler extends AbstractLogOrThrowWorkItemHandler {
private static Utils utils = new Utils();
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
// Throw an error due to many missing parameters on the workitem
String id= (String) workItem.getParameter("ID");
...
try {
RequiredParameterValidator.validate(this.getClass(), workItem);
...
} catch (Throwable e) {
utils.insertErrors(id, errorCode, errorMessage, e.getStackTrace(), -1L); // testing this method called
}
...
}
我意识到我可以对 Utils 使用依赖注入,但我避免使用 Spring。 帖子 关于 模拟静态字段让我感觉我很接近:
@Test
public void executeWorkItemMissingParametersTest() {
Utils mockUtils = mock(Utils.class);
WorkItemManager mockWorkItemMgr = mock(WorkItemManager.class);
EmailNotificationWorkItemHandler mockWorkItemHandler = mock(EmailNotificationWorkItemHandler.class);
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
System.out.println("called with arguments: " + Arrays.toString(args));
return null;
}
}).when(mockUtils).insertErrors(any(), any(), any(), any(), anyLong());
try {
doAnswer(new Answer<Void>() { // Unfinished stubbing detected
public Void answer(InvocationOnMock invocation) {
return null;
}
}).when(mockUtils);
Utils.init();
} catch (Exception e) {
System.out.println("In mocking of Utils.init() " + e.getLocalizedMessage());
}
WorkItemImpl workItem = new WorkItemImpl();
workItem.setParameter("ID", "1111-AAAA");
// Lots of required parameters removed to cause an exception and insertErrors to be called
mockWorkItemHandler.executeWorkItem(workItem, mockWorkItemMgr);
verify(mockUtils).insertErrors(any(), any(), contains("RequiredParameterValidator"), any(), anyLong());
}
但是在mockWorkItemHandler 中使用并调用了Utils 的真实实例(而不是模拟的Utils),并且在上面标记的位置出现“检测到未完成的存根”异常。 我的目标是测试代码中注释的 utils.insertErrors 调用,并在没有 Utils 副作用的情况下执行此操作。 我的模拟中缺少什么(1)使用模拟的 Utils(没有副作用,例如数据库连接)和(2)测试调用 mockWorkItemHandler 的 utils.insertErrors 来记录缺少的参数?
请注意,我已经展示了 EmailNotificationWorkItemHandler 和 Utils 的所有相关部分。
这是一个使用mockito内联模拟构造调用的简单示例。为了启用mockito-inline,你可以参考这个答案,因为mockito默认关闭它。您可以在您的用例中使用它,它应该可以解决您的问题。
消费类
public class ConsumerClass {
Logger logger = LoggerFactory.getLogger(ConsumerClass.class);
private static final Utils utils = new Utils();
public String callUtilMethod(){
logger.info("ConsumerClass callUtilMethod");
return utils.helloWorld();
}
}
实用工具
public class Utils {
Logger logger = LoggerFactory.getLogger(Utils.class);
public String helloWorld() {
logger.info("Utils class Hello World");
return "This is from Utils";
}
}
测试用例
@Test
void testConsumerClass() {
try (MockedConstruction<Utils> mocked = Mockito.mockConstruction(Utils.class, (mock, context) -> {
Mockito.when(mock.helloWorld()).thenReturn("This is from Mock");
})) {
ConsumerClass consumerClass = new ConsumerClass();
Assertions.assertEquals("This is from Mock", consumerClass.callUtilMethod());
}
}