【发布时间】:2020-03-03 16:01:32
【问题描述】:
我正在开发一个在 Maven 模块中拆分的应用程序,如下所示:
- myApp-父级
- 框架
- 模块1
- 坚持
- 服务
- 模块2
- 坚持
- 服务
第一部分:持久层
对于 module1/persistence,源位于包 org.company.myApp.module1.persistence 中,我有以下配置类:
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应用@Configuration。可以用作 Spring 标准 @Configuration 注释的替代品,以便可以自动找到配置(例如在测试中)。
应用程序应该只包含一个@SpringBootConfiguration,大多数惯用的 Spring Boot 应用程序都会从 @SpringBootApplication 继承它。
由于所有模块的最终应用程序将包含多个@SpringBootConfiguration,因此我选择了简单的@Configuration。
第二部分:持久层测试
测试源在同一个包中(当然在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 {
}
extends Module1PersistenceConfiguration 在这里似乎没用,因为两个类在同一个包中,扫描会检测并加载主配置。
@SpringBootApplication 允许我加载 Spring 上下文,因为我使用 @SpringBootTest 进行的测试会检测到此类。
第二个问题:如果我用@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 {
}
由于服务层和持久层没有同一个包,所以我使用@Import(Module1PersistenceConfiguration.class)触发持久层的扫描。
第三个问题:虽然我觉得这很舒服,但也许有更好的选择?服务层应该知道持久层并通过将相应的basePackages 属性添加到@ComponentScan 来执行完整扫描?
最后部分:服务层测试
这是我苦苦挣扎的部分。 我想通过模拟持久层来测试服务层,我设法做到这一点的唯一方法是添加一个排除主配置类的测试配置类,以防止spring尝试加载持久层(由于@ 987654342@ 在主配置中)并失败,因为属性中没有数据源配置(持久性测试资源包含 application.properties 以便使用 H2 嵌入式数据库和 unboundid 嵌入式 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。
最后一个问题:实现这一目标的正确方法是什么? 答案可能是:对您的服务进行单元测试或进行包含持久层的集成测试,但您的半集成测试没有任何意义?
【问题讨论】:
标签: spring spring-boot