我有一个 springboot,正在为其编写单元测试。有一个factoryBean,我在运行时从中获取服务对象。我想测试是否调用了该服务对象上的特定方法。这是应用程序代码
@Component
public class AppClient {
@Autowired
ServiceFactory factory
Service secretService
@postContruct
public void init(){
this.secretService=factory.get("secret");
}
public void process(Map<String, Object> param){
for (String key: param.keySet()){
if (key.equals("foobar")){
restService.handle(param.get(key));
}
}
}
}
这是我的单元测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {
@Autowired
AppClient appClient;
@SpyBean
ServiceFactory factory;
Service secretService;
@Before
public void init(){
this.secretService=Mockito.spy(factory.get("secret"));
}
@Test
public void testProcess() {
Object obj = new MyDummyObject();
Map<String, Object> params = new HashMap<>();
params.put("foobar", obj);
appClient.process(params);
Mockito.verify(secretService).handle(obj);
}
}
测试失败,当我运行调试器时,我看到句柄被调用。那么这里出了什么问题呢?
编辑
@MockBean
ServiceFactory factory;
@Mock
Service secretService
@Before
public void init(){
Mockito.when(factory.get(eq("secret"))).thenReturn(secretService);
}
通过此更改,工厂 bean 被模拟,但在 AppClient 中,secretService 为 null。也就是说,secretService 没有被 stub 。通过调试器进行测试。
最佳答案
PostConstruct
回调在 Spring 应用程序完全运行之前以及您的测试类在工厂模拟上进行一些准备之前执行。您无法在 PostConstruct
回调中运行的代码上声明 Mockito when().then()
期望。
我建议您在 AppClient
bean 中进行基于构造函数的注入(inject):
@Component
public class AppClient {
private final ServiceFactory factory
@Autowired
public AppClient(ServiceFactory factory){
this.factory = factory;
}
...
}
并将其作为简单的单元测试进行测试。通过手动创建 AppClient 的实例,注入(inject)工厂的模拟,执行 init
方法并验证您需要的所有内容:
@Test
void initTest(){
when(factory.get(..)).thenReturn(..);
AppClient client = new AppClient(factory);
client.init();
verify(..)
}
关于java - mockito spy 不适用于工厂 bean 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56573928/