Springboot UT 引入某些类
http://www.infoq.com/cn/articles/Unit-Testing-Complete-Integration-Testing-Begins
https://segmentfault.com/a/1190000010854538
前面一个部分讲解了如何使用Spring Testing工具来测试Spring项目,现在我们讲解如何使用Spring Boot Testing工具来测试Spring Boot项目。
在Spring Boot项目里既可以使用Spring Boot Testing工具,也可以使用Spring Testing工具。
在Spring项目里,一般使用Spring Testing工具,虽然理论上也可以使用Spring Boot Testing,不过因为Spring Boot Testing工具会引入Spring Boot的一些特性比如AutoConfiguration,这可能会给你的测试带来一些奇怪的问题,所以一般不推荐这样做。
例子1:直接加载Bean
使用Spring Boot Testing工具只需要将@ContextConfiguration
改成@SpringBootTest
即可,源代码见FooServiceImpltest:
@SpringBootTest(classes = FooServiceImpl.class)
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
例子2:使用内嵌@Configuration加载Bean
源代码见FooServiceImpltest:
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
@Configuration
@Import(FooServiceImpl.class)
static class Config {
}
}
例子3:使用外部@Configuration加载Bean
@Configuration
@Import(FooServiceImpl.class)
public class Config {
}
@SpringBootTest(classes = Config.class)
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
这个例子和例子2差不多,只不过将@Configuration放到了外部。
例子4:使用@SpringBootConfiguration
前面的例子@SpringBootTest
的用法和@ContextConfiguration
差不多。不过根据@SpringBootTest
的文档:
它会尝试加载
@SpringBootTest(classes=...)
的定义的Annotated classes。Annotated classes的定义在ContextConfiguration中有说明。如果没有设定
@SpringBootTest(classes=...)
,那么会去找当前测试类的nested @Configuration class如果上一步找到,则会尝试查找
@SpringBootConfiguration
,查找的路径有:1)看当前测试类是否@SpringBootConfiguration
,2)在当前测试类所在的package里找。
所以我们可以利用这个特性来进一步简化测试代码。
@SpringBootConfiguration
@Import(FooServiceImpl.class)
public class Config {
}
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
例子5:使用@ComponentScan扫描Bean
前面的例子我们都使用@Import
来加载Bean,虽然这中方法很精确,但是在大型项目中很麻烦。
在常规的Spring Boot项目中,一般都是依靠自动扫描机制来加载Bean的,所以我们希望我们的测试代码也能够利用自动扫描机制来加载Bean。
@SpringBootConfiguration
@ComponentScan(basePackages = "me.chanjar.basic.service")
public class Config {
}
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
例子6:使用@SpringBootApplication
也可以在测试代码上使用@SpringBootApplication
,它有这么几个好处:
自身
SpringBootConfiguration
提供了
@ComponentScan
配置,以及默认的excludeFilter,有了这些filter Spring在初始化ApplicationContext的时候会排除掉某些Bean和@Configuration启用了
EnableAutoConfiguration
,这个特性能够利用Spring Boot来自动化配置所需要的外部资源,比如数据库、JMS什么的,这在集成测试的时候非常有用。
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service")
public class Config {
}
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
@Autowired
private FooService foo;
@Test
public void testPlusCount() throws Exception {
assertEquals(foo.getCount(), 0);
foo.plusCount();
assertEquals(foo.getCount(), 1);
}
}
避免@SpringBootConfiguration冲突
当@SpringBootTest
没有定义(classes=...
,且没有找到nested @Configuration class的情况下,会尝试查询@SpringBootConfiguration
,如果找到多个的话则会抛出异常:
Caused by: java.lang.IllegalStateException: Found multiple @SpringBootConfiguration annotated classes [Generic bean: class [...]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [/Users/qianjia/workspace-os/spring-test-examples/basic/target/test-classes/me/chanjar/basic/springboot/ex7/FooServiceImplTest1.class], Generic bean: class[me.chanjar.basic.springboot.ex7.FooServiceImplTest2]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [...]]
比如以下代码就会造成这个问题:
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service")
public class Config1 {
}
@SpringBootApplication(scanBasePackages = "me.chanjar.basic.service")
public class Config2 {
}
@SpringBootTest
public class FooServiceImplTest extends AbstractTestNGSpringContextTests {
// ...
}
解决这个问题的方法有就是避免自动查询@SpringBootConfiguration
:
定义
@SpringBootTest(classes=...)
提供nested @Configuration class
最佳实践
除了单元测试(不需要初始化ApplicationContext的测试)外,尽量将测试配置和生产配置保持一致。比如如果生产配置里启用了AutoConfiguration,那么测试配置也应该启用。因为只有这样才能够在测试环境下发现生产环境的问题,也避免出现一些因为配置不同导致的奇怪问题。
在测试代码之间尽量做到配置共用,这么做的优点有3个:
能够有效利用Spring TestContext Framework的缓存机制,ApplicationContext只会创建一次,后面的测试会直接用已创建的那个,加快测试代码运行速度。
当项目中的Bean很多的时候,这么做能够降低测试代码复杂度,想想如果每个测试代码都有一套自己的@Configuration或其变体,那得多吓人。
参考文档
例子7:
使用
@ContextHierarchy({
@ContextConfiguration(classes = {ServiceTestConfig.class}, loader = AnnotationConfigContextLoader.class)
})
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(
loader=AnnotationConfigContextLoader.
class
,
classes=ApplicationContextTestResourceNameType.
class
)
public
class
FieldResourceInjectionTest {
@Resource
(name=
"namedFile"
)
private
File defaultFile;
@Test
public
void
givenResourceAnnotation_WhenOnField_ThenDependencyValid(){
assertNotNull(defaultFile);
assertEquals(
"namedFile.txt"
, defaultFile.getName());
}
}
@Configuration
public
class
ApplicationContextTestResourceNameType {
@Bean
(name=
"namedFile"
)
public
File namedFile() {
File namedFile =
new
File(
"namedFile.txt"
);
return
namedFile;
}
}
Springboot UT 引入某些类的更多相关文章
- Thinkphp 零散知识点(caa/js路径,引入第三方类,ajax返回,session/cookie)
一.关于JS和CSS路径问题 1.找路径是从入口文件index.php来找的,而不是从文件本身所在位置来找, 因为我们访问时是访问的入口文件 2.在存放JS和CSS的时候可以放到public文件夹下 ...
- 尚硅谷springboot学习5-主入口类说明
package com.atguigu; import org.springframework.boot.SpringApplication; import org.springframework.b ...
- SpringBoot启动加载类ApplicationRunner
SpringBoot启动加载类ApplicationRunner 有时希望项目在启动的时候加载一些系统参数,就要用到ApplicationRunner ApplicationRunner是一个接口,我 ...
- springboot服务引入外部jar包在windows运行正常,在linux环境上无法加载到引入jar包的类
一.问题描述 最近开发了一个springboot程序,需要依赖第三方jar包,这个jar包无法直接通过pom远程仓库下载,需要从自己本地引入,于是配置pom文件如下:将本地jar包引入工程,syste ...
- springboot中引入zookeeper,生成 配置类
1.application.properties zookeeper.address=@mvn.zookeeper.address@ zookeeper.namespace=@mvn.zookeepe ...
- SSM项目 以及 springboot 中引入swagger2的方法
swagger2是一个非常好用的接口文档,在开发的过程中方便前后端接口的交接. 下面我们就来讲讲在使用java时,分别在SSM框架,以及springboot+mybatis框架中引入swagger2的 ...
- SpringBoot入门02-配置类
引入 Spring Boot的底层已经有了Spring MVC Spring Boot习惯优先的思想,很多配置都是可省的 不需要配置web.xml文件 不需要服务层的xml配置 不需要dao层的xml ...
- SpringBoot内置工具类,告别瞎写工具类了
不知大家有没有注意到,接手的项目中存在多个重复的工具类,发现其中很多功能,Spring 自带的都有.于是整理了本文,希望能够帮助到大家! 一.断言 断言是一个逻辑判断,用于检查不应该发生的情况 Ass ...
- 引入DecimalFormat类进行数字格式化操作
引入语句:import java.text.DecimalFormat; 首先创建DecimalFormat类对象,利用类对象调用Format()方法进行格式化操作.这里有两种方法:①.Decimal ...
随机推荐
- 基于springboot的spring JSR validation 后台参数验证
springboot集成JSR参数校验: 1. 导入maven <dependency> <groupId>org.springframework.boot</group ...
- MySQL数据库事务各隔离级别加锁情况--read committed && MVCC(转)
本文转自https://m.imooc.com/article/details?article_id=17290 感谢作者 上篇记录了我对MySQL 事务 隔离级别read uncommitted的理 ...
- 跟我一起学extjs5(08--自己定义菜单1)
跟我一起学extjs5(08--自己定义菜单1) 顶部和底部区域已经作好,在顶部区域有一个菜单的button.这一节我们设计一个菜单的数据结构,使其能够展示出不相同式的菜单.因为准备搭建的是一个系统模 ...
- NodeJS学习资料合集
1. 官网 nodejs 2. How do I get started with Node.js,stackoverflow提问,收集非常多实用的网站 3. node-books.github收 ...
- Nginx和Tomcat负载均衡实现session共享
以前的项目使用Nginx作为反向代理实现了多个Tomcat的负载均衡,为了实现多个Tomcat之间的session共享,使用了开源的Memcached-Session-Manager框架. 此框架的优 ...
- 解决Sqoop报错Could not load db driver class: com.intersys.jdbc.CacheDriver
报错栈: // :: INFO tool.CodeGenTool: Beginning code generation // :: ERROR sqoop.Sqoop: Got exception r ...
- 采用Operator-sdk轻松将helm chart转为Operator
去年就接触Operator,从Oracle发布的WebLogic Operator到mySQL Operator,构建的源码一大堆,但感觉一直缺少合适的开发框架能够避免复杂性快速生成, 随着技术的日益 ...
- ELK kibana查询与过滤
在kibana中,可通过搜索查询过滤事务或者在visualization界面点击元素过滤. 创建查询 在Discover界面的搜索栏输入要查询的字段.查询语法是基于Lucene的查询语法.允许布尔运算 ...
- 给定任意字符串,计算一共能组合成多少个单词bing
CSDN编程挑战里的题目 例如有一个字符串"iinbinbing",截取不同位置的字符‘b’.‘i’.‘n’.‘g’组合成单词"bing".若从1开始计数的话, ...
- [Linux]在终端启动程序关闭终端不退出的方法
一般情况下关闭终端时,那么在这个终端中启动的后台程序也会终止,要使终端关闭后,后台程序保持执行,使用这个指令: nohup 命令 & 如:nohup test.sh & 回车,然后提示 ...