SPRING BOOT 环境下,测试有时会依赖于外部的中间件,如Mysql,Activemq,Mongodb等,那如何能减少这种依赖呢?
SPRING BOOT其实已经实现了自动化配置。
Mongodb
SPRING BOOT的自动化配置文件:org.springframework.boot.autoconfigure.mongo.embeddedEmbedded.MongoAutoConfiguration.java
在pom.xml中新增一test profile,并添加相应jar包,这样可防止对其他profile的影响,如果是在Eclipse跑测试,需在Project的属性中指定Active Profile为test,以覆盖pom.xml的定义。
这种方式即使是使用SPRING DATA MONGODB的REPOSITORY也是适用的。
<profile>
<id>test</id>
<dependencies>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
在application-test.yaml中添加端口,其他如IP那些信息都不需要
spring:
data:
mongodb:
port: 27017
unit test config
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.util.FileCopyUtils;
@Configuration
@Profile({"test", "integrationTest"})
@EnableMongoRepositories(
basePackages = {"paul.com.repository"
}
)
public class EmbeddedDataSourceConfiguration {
@Value("classpath:/initdata/USER.json")
private Resource userResource;
@Value("classpath:/initdata/MEMBERS.json")
private Resource membersResource;
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private DataSource dataSource;
@Autowired
private MongoTemplate mongoTemplate;
@PostConstruct
protected void initialize() throws FileNotFoundException, IOException {
this.initializeHsqldb();
this.initializeMongodb();
}
private void initializeHsqldb() {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(resourceLoader.getResource("classpath:/org/springframework/batch/core/schema-hsqldb.sql"));
populator.setContinueOnError(true);
DatabasePopulatorUtils.execute(populator , dataSource);
}
private void initializeMongodb() throws FileNotFoundException, IOException {
this.saveResource(userResource, "USER");
this.saveDocumentList(membersResource, "MEMBER");
}
private void saveResource(Resource resource, String collectionName) {
String resourceJson = this.asString(resource);
Document resourceDocument = Document.parse(resourceJson);
this.mongoTemplate.save(resourceDocument, collectionName);
}
private void saveDocumentList(Resource resource, String collectionName) {
String resourceJson = this.asString(resource);
Document resourceDocument = Document.parse("{ \"list\":" + resourceJson + "}");
List<Document> documentList = resourceDocument.get("list", List.class);
documentList.forEach(document -> this.mongoTemplate.save(document, collectionName));
}
private String asString(Resource resource) {
try (Reader reader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8)) {
return FileCopyUtils.copyToString(reader);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
// @Bean(destroyMethod="close")
// public DataSource dataSource() {
// BasicDataSource dataSource = new BasicDataSource();
// dataSource.setDriverClassName(environment.getProperty("batch.jdbc.driver"));
// dataSource.setUrl(environment.getProperty("batch.jdbc.url"));
// dataSource.setUsername(environment.getProperty("batch.jdbc.user"));
// dataSource.setPassword(environment.getProperty("batch.jdbc.password"));
// return dataSource;
// }
}
ActiveMQ
只需更改application-test.yml中的brokerUrl为vm://embedded即可
spring:
activemq:
broker-url: vm://embedded?broker.persistent=false,useShutdownHook=false
in-memory: true
non-blocking-redelivery: true
#packages:
#trust-all: false
#trusted: com.memorynotfound
pool:
block-if-full: true
block-if-full-timeout: -1
create-connection-on-startup: true
enabled: false
expiry-timeout: 0
idle-timeout: 30000
max-connections: 1
maximum-active-session-per-connection: 500
reconnect-on-exception: true
time-between-expiration-check: -1
use-anonymous-producers: true
user: admin
#password: ENC(hWJHuMyhydTqyF32neasTw==)
password: admin
关系型数据库
将在application-test.yml中的数据库信息删除,同时在pom.xml中添加jar包依赖,这边是采用HSQL数据库
<profile>
<id>test</id>
<dependencies>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
非SPRING BOOT/SPRING的纯JDK环境可参考
https://github.com/yandex-qatools/embedded-services
https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo
https://github.com/jonyfs/spring-boot-data-embedded-mongodb/blob/master/src/main/java/br/com/jonyfs/spring/boot/data/embedded/mongodb/config/MongoConfig.java
ActiveMQ:
https://memorynotfound.com/spring-boot-embedded-activemq-configuration-example/