Java 基于profile-Spring-Boot的自动连线实现

Java 基于profile-Spring-Boot的自动连线实现,java,testing,spring-boot,spring-test,Java,Testing,Spring Boot,Spring Test,我正在用Spring Boot开发一个RESTAPI,问题是我有一个接口和两个实现,我只想用模拟实现进行测试 Interface CRMService @Service CRMServiceImpl @Service CRMServiceMock 实现:第一个是与后端的真正集成,第二个是用于测试目的的模拟,最好的方法是什么?集成测试还是基于活动配置文件的测试?如果我需要基于概要文件自动连接服务,那么最佳做法是什么?虽然我确信有例外,但通常不应该是集成或单元测试(通常涉及模拟),而是两者都

我正在用Spring Boot开发一个RESTAPI,问题是我有一个接口和两个实现,我只想用模拟实现进行测试

Interface CRMService 

@Service
CRMServiceImpl

@Service
CRMServiceMock

实现:第一个是与后端的真正集成,第二个是用于测试目的的模拟,最好的方法是什么?集成测试还是基于活动配置文件的测试?如果我需要基于概要文件自动连接服务,那么最佳做法是什么?

虽然我确信有例外,但通常不应该是集成或单元测试(通常涉及模拟),而是两者都有;参见测试金字塔概念

集成测试:只需使用真正的服务。如果它调用其他实况服务,那么考虑将URL作为Spring启动属性注入到测试环境中的模拟服务器(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)'时,返回指定的字符串”

这种方式允许您在必要时仍然使用mock,但避免了维护整个mock实现概要文件,并避免了自动连接内容的问题

最后,如果您需要一个完全独立的实现,请考虑不要自动布线服务!相反,在配置类中使用
@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());
    }
}
例如,如果希望在内存存储和实际数据库连接层之间切换,则可以使用^^^


就我个人而言,我建议像上面的例子那样进行依赖注入,即使没有多个实现,因为随着项目的发展,如果自动连接属性失败,可能很难找到确切的原因。此外,明确显示依赖项的来源有助于组织应用程序和可视化应用程序层次结构。

我相信配置文件也会以更简洁的方式处理它(您使用inMem变量发布的内容)。@SirKometa是的,没错,虽然我想这取决于你想要的变化的数量。如果只有几个,那么也许是个人资料;如果很多,那么操作单个值可能比枚举所有必需的配置文件更容易。