Java Mock final void method using Mockito



我需要一些帮助来理解如何对以下内容进行单元测试。我有以下类结构。我必须按原样遵循结构,因为这是根据我们产品的框架,我不能偏离这一点。

package com.rohan.base
import javax.inject.Inject;
public abstract class ServiceBase {
@Inject
protected CommandExecutorBase commandExecutor;
public final void execute() {
commandExecutor.execute(this);
}   
}
--------------------------------------------------------
package com.rohan.services
public class MyService extends ServiceBase {
public void someMethod() {} 
}
--------------------------------------------------------
package com.rohan.delegates
import javax.inject.Inject;
import com.rohan.services.MyService
public class MyDelegate {
@Inject
MyService myService;
public void callService() {
myService.execute();
}   
}

我正在尝试为编码执行 TDD 方法,并且我想确保委托类中的callService方法调用 Service 类上的execute方法。

我尝试了以下方法,但它在执行方法中给了我一个 Null 指针异常(因为commandExecutor对象为 null(。 有人可以告诉我如何做到这一点吗? 我不被允许使用PowerMockito。

import org.junit.Test;
import org.mockito.Mockito;
public class MyDelegateUnitTests {
@Test
public void validateServiceExecuteIsCalled() {
MyDelegate delegate = new MyDelegate();
MyService serviceObject = Mockito.mock(MyService.class);
delegate.myService = serviceObject;
Mockito.doAnswer((i) -> {
System.out.println("I am here");
return null;
}).when(serviceObject).execute();
Mockito.verify(serviceObject, Mockito.times(1)).execute();
}   
}

我不能模拟命令执行器对象,因为它不可访问(与我的委托类不同的包(。 代替Mockito.doAnswer(),我也尝试了Mockito.doNothing().when(serviceObject).execute();
但我得到了同样的例外。有人可以告诉我,当我尝试在when方法中定义模拟时,为什么它会继续并尝试执行真正的方法? 谢谢!

更新我修改了测试类,并添加了文件夹/文件模拟扩展名(如@jokster在下面的答案中建议的那样(。但是,我最终会遇到以下例外。我正在使用Mockito 2。

我的测试类:

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
public class MyDelegateUnitTests {
MyDelegate delegate;
MyService serviceObject;
@Before
public void setUpMocks() {
delegate = new MyDelegate();
serviceObject = Mockito.mock(MyService.class);
Mockito.doNothing().when(serviceObject).execute();
delegate.myService = serviceObject;     
}
@Test
public void validateSettersAreCalled() {
delegate.callService();
Mockito.verify(serviceObject, Mockito.times(1)).execute();
}
}

我得到以下异常:

java.lang.ExceptionInInitializerError: null
at org.mockito.internal.configuration.plugins.Plugins.getStackTraceCleanerProvider(Plugins.java:17)
at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:41)
at org.mockito.exceptions.base.MockitoException.<init>(MockitoException.java:30)
at org.mockito.exceptions.misusing.MockitoConfigurationException.<init>(MockitoConfigurationException.java:18)
at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:66)
at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:24)
at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:12)
at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:11)
at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
at org.mockito.internal.MockitoCore.<init>(MockitoCore.java:44)
at org.mockito.Mockito.<clinit>(Mockito.java:975)
at com.rohan.delegates.MyDelegateUnitTests.setUpMocks(MyDelegateUnitTests.java:16)

根据此文档 https://www.baeldung.com/mockito-final,您必须激活模拟最终方法:只需创建一个文件src/test/resources/mockito-extensions/mock-marker-inline

然后最终方法应该像其他方法一样工作。

作为单元测试的一部分,我认为不需要定义myService.execute方法的行为。定义行为是不必要的

Mockito.doAnswer((i) -> {
System.out.println("I am here");
return null;
}).when(serviceObject).execute();

您可以删除上面的代码。

验证是否以正确的次数调用了execute方法就足够了。为了回答您的问题,一个建议是基于构造函数的注入。基本上创建一个构造函数MyDelegate并注入Myservice。在测试中,执行以下操作:

MyService serviceObject = Mockito.mock(MyService.class);      
MyDelegate delegate = new MyDelegate(serviceObject);

另一种选择是在测试中使用@InjectMocks@Inject,如果您不想在委托类中使用基于构造函数的注入。

最新更新