虽然我确定有例外,但通常不应该是集成或单元测试(通常涉及模拟),而是两者兼而有之;请参阅测试金字塔概念。
集成测试:只使用真正的服务。如果它调用其他实时服务,则考虑将 URL 作为 Spring Boot 属性注入,这些属性指向测试环境中的模拟服务器(Node.js 或其他简单快捷的东西)。
单元测试:考虑使用像 Mockito 这样的测试框架。使用它,您可以使用模拟编写测试,大致如下:
private CRMServiceImpl mockService = mock(CRMServiceImpl.class);
@Test
public void someTest() {
when(mockService.someMethod(any(String.class), eq(5))).thenReturn("Hello from mock object.")
}
上面的例子大致翻译为“当某个类在你的服务上调用'someMethod(String, int)'时,返回指定的字符串”。
这种方式允许您在必要时仍然使用模拟,但避免维护整个模拟实现配置文件并避免自动连接的问题。
最后,如果您需要完全独立的实现,请考虑不要使用自动装配服务!相反,在您的配置类中使用 @Bean 注释,并通过构造函数将其注入到需要它的类中。像这样:
@Configuration
public class ApplicationConfiguration {
@Value{$"service.crm.inmem"} // Injected property
private boolean inMem;
@Bean
CRMService getCRMService() {
if (inMem) {
return new CRMServiceMock();
}
return new CRMServiceImpl();
}
@Bean
OtherService getOtherService() {
// Inject CRMService interface into constructor instead of auto-wiring in OtherService.class
return new OtherService(getCRMService());
}
}
当你想在内存存储和真正的数据库连接层之间切换时,你可以使用 ^^ 的一个例子。
我个人建议即使没有多个实现,也像上面的示例一样进行依赖注入,因为随着项目的增长,如果自动连接的属性失败,可能很难准确找出原因。此外,明确显示依赖项的来源有助于组织应用程序和可视化应用程序层次结构。