【发布时间】:2020-08-31 13:38:27
【问题描述】:
我正在使用 JUnit5 来测试 Spring Boot 应用程序。我想测试一个使用@Autowired 字段的@Service 对象。我想模拟我的测试对象间接使用的另一个 @Service 对象。具体来说,我有以下(高度简化的)设置:
正在测试的对象:
@Service
public class MainService {
private @Autowired SubService subService;
public String test() {
return subService.test();
}
}
SubService:
@Service
public class SubService {
private @Autowired StringService stringService;
public String test() {
return stringService.test();
}
}
StringService:
@Service
public class StringService {
public String test() {
return "Real service";
}
}
使用的测试类:
@SpringBootTest
public class MainServiceTest {
private @Autowired MainService mainService;
private @MockBean StringService stringService;
@BeforeEach
public void mock() {
Mockito.when(stringService.test()).thenReturn("Mocked service");
}
@Test
public void test() {
assertEquals("Mocked service", mainService.test());
}
}
如果我以@SpringBootTest 运行测试类,则上述方法有效,但这会加载完整的应用程序并且非常慢。我也想避免@WebMvcTest,因为我不需要网络服务器,或者@DataJpaTest,因为我不需要持久性。我不想模拟SubService,因为它包含我想与MainService 一起测试的功能。
我尝试了以下方法:
-
@ExtendWith(SpringExtension.class)=> 抛出NoSuchBeanDefinitionException,在这种情况下似乎自动装配不起作用 -
@ExtendWith(MockitoExtension.class)并使用@InjectMocks和@Mock而不是 Spring 注释 => 因为StringService不是正在测试的MainService的直接字段,这不起作用。
有没有办法在不加载 web 服务器或持久层的情况下使用 spring 依赖注入系统,或者不使用 Spring 测试但允许“嵌套”依赖注入?
【问题讨论】:
-
您要测试哪个类?为什么在测试MainService的时候不能mock SubService,单独为SubService写单元测试?
-
@msfoster 我正在测试 MainService。从技术上讲,我可以模拟 SubService,但我不想这样做,因为它在底层实现中没有多大意义(模拟只是 SubService 中代码的副本)。
-
存根很简单,适合测试用例。为什么要复制实现?
-
如果你提供了一个你想测试的方法的例子,你会更容易得到帮助:)
-
我看到您已经在测试中使用了 Mockito 依赖项,并且您想避免使用
SpringBootTest,为什么不使用 Mockito 的 @Mock 和 @InjectMock 来对您需要的内容进行单元测试?
标签: spring spring-boot junit mockito