我有一个 Spring Boot 服务实现,它与三个不同的外部服务(API 和 SOAP Web 服务)进行通信。有时,这些服务可能会进入维护状态,我需要实现一种机制来“绕过”或“模拟”它们。我为实现此目的而采用的方法是在属性文件中包含一些条目:
service1.bypass.enable=true
service2.bypass.enable=true
service3.bypass.enable=true
因此,在我的代码中,我只需要验证这些属性的值是否设置为 true,并使用正确的实现或绕过(返回模拟)。
@Value("service1.bypass.enable")
private boolean service1Bypass;
//Inside the methods
if (!service1Bypass) {
callService();
} else {
callMock();
}
这在 SonarQube 扫描我的代码时造成了一些麻烦,因为我需要测试每个服务何时被模拟或不被模拟,我认为这是不相关的。您知道是否有任何解决方法或更好的方法来编码?该项目使用 Spring 和 Maven 以及 Java 8
最佳答案
我认为“绕过”和“ mock ”之间存在误解。
当您绕过某项服务时,意味着您“跳过”它,换句话说,您不会调用该服务并继续执行后续步骤。
当您“模拟”一个服务时,您的逻辑并不是“跳过”对该服务的调用,而是创建一个组件(属于您的代码项目)来模仿该服务的行为真正的服务,但它会返回一些“测试”或“假”响应。
模拟对于测试或您所描述的场景来说是非常有用的技术,在这种场景中,您正在使用的许多服务可能会进入维护状态并影响其他想要使用您的服务的人。
现在,回到你遇到的问题,你可以通过两种方式解决这个问题,第一种,如果你使用 Jacoco Coverage 插件,那么只需将以下标签添加到你的 pom.xml 文件中(因为我相信您正在使用 Maven)。
<properties>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPaths>target/jacoco.exec</sonar.jacoco.reportPaths>
<sonar.language>java</sonar.language>
<sonar.exclusions>YOUR PACKAGES GOES HERE</sonar.exclusions>
</properties>
除此之外,我相信你的方法还不错,但它可能会导致一些问题,例如:
- 您将“模拟”逻辑混合在业务逻辑中,这可能有点困惑。
- 当使用SonarQube(静态分析)等工具分析代码时,您会发现每个条件通常都需要一个测试用例(我认为这就是您遇到的问题)
- 您现在使用三个属性,因为您连接到三个服务,但如果您需要使用八个或九个服务怎么办?您会添加八个或九个属性吗?我的意思是,你可以,但恕我直言,可能会有点困惑。
由于您已经在使用 Spring,我相信解决问题的一个好方法不仅仅是解决问题,而是查看 Spring Profiles .
有关更详细的教程,您还可以查看:https://www.baeldung.com/spring-profiles
让我们为您的案例举一个例子:
- 您只需在属性文件中定义一个属性,而不是为每个服务定义一个属性,该属性称为:
spring.profiles.active
- 您可以为该属性分配一个或多个值(以逗号分隔)。
例如:
如果您想模拟其中一项服务,可以使用以下命令:spring.profiles.active=mockservice1
如果你想模拟两个(或更多)服务:spring.profiles.active=mockservice1,mockservice2
- 您无需使用条件结构,而是为要模拟的每个服务创建一个类,并使用
@Profile(“mockservice1”)
进行注释或通过@Configuration
进行处理或@Bean
注释。
希望这可以在某种程度上帮助您解决问题。
关于java - SonarQube 对使用模拟组件的 Spring 应用程序的条件进行严格测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51849916/