问题描述
嗨,我正在尝试使用异步方法进行一些单元测试。下面是我的代码。我嘲笑 doWork 的 methodUndertest() 的第一行在执行期间返回 null 并且测试失败。我尝试了与异步相关的不同事情,但没有任何效果。我在这里错过了什么。
public class AServiceImpl{
@Autowired
BService bService;
@Async
public CompletableFuture<String> methodUnderTest(String input){
String s = bService.doWork(input.substring(3));
//blah blah blah
return CompletableFuture.completedFuture(s);
}
}
public class AServiceTest{
private BService bService;
private AService aService;
@Before
void beforetest(){
aService = new AServiceImpl();
bService = mock(BService.class);
//blah blah blah
}
@Test
public void someUnittest(){
Mockito.when(bService.doWork(any())).thenReturn("ABC");
String s = aService.methodUnderTest("ABCDEF").get();
Assert.assertNotNull(s);
}
}
解决方法
此处与 @Async
无关。测试中的模拟设置没有分配给被测对象。
首先,我建议避免使用 Autowired 字段,并让您的类通过构造函数依赖项显式公开它们的依赖项
public class AServiceImpl {
private final BService bService;
@Autowired
public AServiceImpl(BService bService) {
this.bService = bService;
}
@Async
public CompletableFuture<String> methodUnderTest(String input) {
String s = bService.doWork(input.substring(3));
//...
return CompletableFuture.completedFuture(s);
}
}
然后在测试时显式注入依赖
public class AServiceTest{
private BService bService;
private AService aService;
@Before
void beforeTest() {
bService = mock(BService.class);
aService = new AServiceImpl(bService); //<-- injecting mocked dependency
//...
}
@Test
public void someUnitTest(){
// Arrange
Mockito.when(bService.doWork(any())).thenReturn("ABC");
// Act
String s = aService.methodUnderTest("ABCDEF").get();
// Assert
Assert.assertNotNull(s);
}
}
,
您的自动接线仅适用于生产代码。您需要在测试中手动注入模拟 BService
。
@Before
void beforeTest() {
aService = new AServiceImpl();
bService = mock(BService.class);
aService.bService = bService;
...
}
您可以使用 spring 运行测试以使用 @RunWith(SpringRunner.class)
(JUnit 4) 或 @ExtendWith(SpringExtension.class)
(Junit 5) 注入测试依赖项。