当前位置: 首页 > 知识库问答 >
问题:

Spring boot多模块配置和测试隔离

荆乐
2023-03-14

我正在开发一个分为maven模块的应用程序,如下所示:

  • myApp家长
  • 坚持

第一部分:持久层

对于module1/persistence,源代码位于包org中。公司我的应用。模块1。持久性我有一个配置类:

package org.company.myApp.module1.persistence;

import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.data.ldap.repository.config.EnableLdapRepositories;

import org.company.myApp.framework.FrameworkConfiguration;

@Configuration
@Import(FrameworkConfiguration.class)
@EntityScan
@ComponentScan
@EnableLdapRepositories("org.company.myApp.module1.persistence.ldap")
@EnableJpaRepositories("org.company.myApp.module1.persistence.db")
public class Module1PersistenceConfiguration {

}

第一个问题:我在这里使用了@Configuration。我没有把@SpringBootApplication放进去,因为持久性不是一个独立的应用程序,而是一种库。然而,我应该在这里使用@SpringBootConfiguration而不是@Configuration

看起来@SpringBootConfiguration只是@Configuration的别名,但尽管我读了很多文章,我还是不清楚。

留档指出:

指示一个类提供Spring Boot应用程序@配置。可以用作Spring标准@配置注释的替代,以便可以自动找到配置(例如在测试中)。

应用程序应该只包含一个@SpringBootConfigance,大多数惯用的Spring Boot应用程序将从@SpringBootApplication继承它。

由于包含所有模块的最终应用程序将包含多个@SpringBootConfigance,所以我选择了简单的@Configance

第二部分:持久层测试

测试源在同一个包中(当然在src/test/java下),我创建了一个特定于测试的配置类:

package org.company.myApp.module1.persistence;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.ldap.LdapProperties;
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.ldap.core.support.LdapContextSource;

@SpringBootApplication
public class Module1PersistenceTestConfiguration extends Module1PersistenceConfiguration {

}

extensed Module1PersistenceConfiguration在这里似乎没有用,因为这两个类都在同一个包中,扫描将检测并加载主配置。

@SpringBootApplication允许我在使用@SpringBootTest检测此类时加载Spring上下文。

第二个问题:如果我用@SpringBootConfiguration注释主配置,Module1PersistenceTestConfiguration会没有用吗?正确的方法是什么?

第三部分:服务层

配置类:

package org.company.myApp.module1.service;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import org.company.myApp.module1.persistence.Module1PersistenceConfiguration;

@Configuration
@ComponentScan
@Import(Module1PersistenceConfiguration.class)
public class Module1ServiceConfiguration {

}

由于服务层和持久化层不具有相同的包,我使用@导入(Module1PeristenceConfiguration.class)来触发持久化层的扫描。

第三个问题:虽然我对此感到满意,但也许还有更好的选择?服务层应该知道持久性层,并通过将相应的basePackages属性添加到@ComponentScan

最后一部分:服务层测试

这是我正在努力解决的问题。我想通过模拟持久性层来测试服务层,唯一的方法是添加一个测试配置类,该类排除了主配置类,以防止spring尝试加载持久性层(由于主配置中的@Import)并失败,因为属性中没有数据源配置(持久性测试资源包含application.properties,以便使用H2嵌入式数据库和未绑定的嵌入式LDAP):

package org.company.myApp.module1.service;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.FilterType;

@SpringBootApplication
@ComponentScan(excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, value = Module1ServiceConfiguration.class))
public class Module1ServiceTestConfiguration {

}

此外,我被迫嘲笑每一个测试中来自持久性层的所有bean。

最后一个问题:实现这一目标的正确方法是什么?答案可能是:对您的服务进行单元测试,或者进行集成测试,其中包括持久性层,但您的半集成测试没有任何意义?

共有1个答案

谷越
2023-03-14

我没有问过,但在这个回答中,我假设您谈论的是maven模块,而不是java模块。如果你说的是Java模块,大多数仍然成立,但可能不是所有。

你有很多问题,我不确定我能回答所有问题,但我可以和你分享我控制SpringBootTest上下文的策略。

通常,我只在需要检查某个特定配置是否正确加载,或者测试控制器或客户机时才编写SpringBootTests。对于其他任何东西,我都会编写常规的单元测试(是的,当它们是服务时)。将测试上下文保持在小范围内,并与要测试的类保持局部关系。只将特定测试真正需要的bean加载到上下文中。如果不加以控制,测试上下文可能会成为维护的地狱。不要创建一个大规模的测试配置。因为在某些情况下,一些bean需要被模仿,而在其他情况下,你不想模仿它们。这可能会成为一场噩梦

通常,我的SpringBootTests设置如下:

@SpringBootTest(classes = MyService.class)
@Import(MyServiceTestConfiguration.class)
class MyServiceTest {
   // test logic
}

@TestConfiguration
class MyServiceTestConfiguration.class {

    @MockBean
    BeanINeedMocked beanINeedMocked;
    // or whatever other strategy you want to use to create a mocked bean
}

通过在@SpringBootTest下定义类,它不会在类路径上寻找@SpringBootApplication。当测试加载时,Spring上下文将加载所提到的类(我相信同一包中的任何其他Bean)。如果您需要任何其他非mocked bean来获得要加载的应用程序上下文,请将它们包含在@SpringBootTest(类={MyService.class,WhatEver其他BeanYouNeed.class}但只加载您需要测试的任何您想测试的内容!

这样你就不需要一个测试配置。为您的应用程序中的所有springboottests初始化,并且每当您向应用程序添加新的SpringBean时,您不会有3000个测试失败。

最后两个注意事项:确保SpringBootApplication类位于应用程序的根上(所有模块共享的根路径)。这样你就不必使用@ComponentScan之类的东西了。只要所有@Configuration、@Service、@组件都有SpringBootApplication所在位置的完整路径,所有组件都将被自动扫描和加载。

如果操作正确,并且所有maven模块都连接正确,就不必从其他模块导入配置。只要模块依赖于它需要SpringBean的模块,它就应该自动接线。

此外,如果您使用@SpringBootApplication,我不会在任何地方使用@SpringBootConfiguration,只会坚持使用@Configuration。

 类似资料:
  • 我正在尝试为一个现有的应用程序编写单元测试用例,该应用程序有多个模块,每个模块中都有主类。有多个类具有\@SpringBootApplication。我写了一个简单的测试用例,它失败了,错误如下。我如何继续我的测试用例中的一个。 java.lang.IllegalStateException:在文件[C:\My Data\Workspace\Services2\MicroServices\Repo

  • 我的问题是关于测试多模块Spring Boot应用程序。 我有一个多模块spring boot REST应用程序。应用程序的结构如下: 以上就是我的应用程序的结构。 SpringBootMainApplication是主要项目。SpringbootModule是SpringBootMainApplication中的子项目。“SpringBootMainApplication.war”WAR将在WA

  • 我在SpringBoot项目中运行测试时遇到了一些问题。 项目结构如下: 项目结构图像 我可以毫无问题地启动resourceService,但是如果我尝试运行SpringBoot项目的标准测试..... 程序响应此错误: 所以我试图将application.properties特定属性从 到 更改后,我注意到resourceserviceApplication无法启动,因为它找不到log4j2.x

  • 本文向大家介绍Springboot Cucumber测试配置介绍详解,包括了Springboot Cucumber测试配置介绍详解的使用技巧和注意事项,需要的朋友参考一下 目前Spring-boot成为了java开发的主流框架,Cucumber作为一款支持dsl的自动化测试工具,很适合用户编写DSL优化过的单元测试等测试用例。本文将讲解如何在SpringBoot中配置Cucumber进行自动化测试

  • 一、简介 黄页模块的基本设置 二、基本设置 三、SEO设置 二、权限设置

  • SOFABoot 模块是一个普通的 Jar 包加上一些 SOFABoot 特有的配置,这些 SOFABoot 特有的配置,让一个 Jar 包能够被 SOFABoot 识别,使之具备模块化的能力。 一个完整的 SOFABoot 模块和一个普通的 Jar 包有两点区别: SOFABoot 模块包含一份 sofa-module.properties 文件,这份文件里面定义了 SOFABoot 模块的名称