spring - 有没有办法在 Spring Boot 中测试没有 Web 或持久层的嵌套对象?
问题描述
我正在使用 JUnit5 来测试 Spring Boot 应用程序。我想测试一个@Service
使用@Autowired
字段的对象。我想模拟@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());
}
}
如果我将测试类作为 a 运行,则上述方法有效@SpringBootTest
,但这会加载完整的应用程序并且非常慢。我也想避免@WebMvcTest
,因为我不需要 Web 服务器,或者@DataJpaTest
因为我不需要持久性。我不想模拟SubService
,因为它包含我想与MainService
.
我尝试了以下方法:
@ExtendWith(SpringExtension.class)
=> throwsNoSuchBeanDefinitionException
,在这种情况下似乎自动装配不起作用@ExtendWith(MockitoExtension.class)
并使用@InjectMocks
and@Mock
而不是 Spring annotations => 因为StringService
不是MainService
被测试的直接字段,这不起作用。
有没有办法在不加载 web 服务器或持久层的情况下使用 spring 依赖注入系统,或者不使用 Spring 测试但允许“嵌套”依赖注入?
解决方案
您可以使用分析(即 Spring @Profile
)来避免加载整个应用程序。它看起来像下面这样:
@Profile("test")
@Configuration
public class TestConfiguration {
@Bean
public MainService mainService() {
return new MainService();
}
@Bean
public SubService subService() {
return new SubService();
}
// mock the StringService
@Bean
public StringService stringService() {
return Mockito.mock(StringService.class);
}
}
然后将该配置文件与 `@SpringBootTest(classes = TestConfiguration.class) 一起使用,它将如下所示:
@ActiveProfiles("test")
@SpringBootTest(classes = TestConfiguration.class)
class MainServiceTest {
@Autowired
private MainService mainService;
@Test
public void test() {
// configure behavior using apis like when(), basically however you
// want your mock to behave
}
}
这将只加载类中定义的 bean TestConfiguration
。注意:由于您的问题更多是关于如何避免加载整个应用程序,因此我已经回答了重点。上述方法将完成工作,但我更喜欢构造函数接线,而不是任何一天的任何其他依赖注入模式,它更容易维护和测试(比如你想要模拟的情况)。
推荐阅读
- android - 未来函数构建器之后的代码未执行
- macros - 气流默认变量 - 增量负载设置
- javascript - React:如何将数据传递给孩子
- javascript - 用对象反应减速器更新问题
- python - 按时间段的python数据框内部连接
- c# - MS Access 链接到 Sharepoint 列表添加新行而不是更新
- javascript - 使用 Luxon 中的特定格式将字符串格式化为日期时间
- mysql - 从表中为 payment_id 选择 'FAILURE' 状态记录,这些记录在 5 分钟内没有任何 'SUCCESS' 状态更新
- c# - ND 数组到 1D 数组之间的 NumSharp 点积会引发 errpr
- html - SVG 线性渐变,UserSpaceOnUse