Spring集成Junit
一个程序的入口是main方法,但是junit中不存在main方法,是因为junit内部的原理是它自己内部就有个main方法,运行扫描带@Test注解的方法,然后反射调用该方法,完成测试。
@Test
public void function(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountDao accountDao1 = applicationContext.getBean("AccountDao", AccountDao.class);
accountDao1.findAll();
}
但是每个测试代码中都会重复这两句话,所以我们可以抽取它们出来
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountDao accountDao1 = applicationContext.getBean("AccountDao", AccountDao.class);
我们可以在外面定义一个全局变量,用来存储accountDao的值,并且通过@Autowired注解实现注入对象,这样每个方法就都可以使用它了.
@Autowired
private AccountDao accountDao;
但是这样运行之后会爆出空指针异常!!!
这是因为Junit默认是不认识Spring框架的,所以它内部没有IOC容器,这样就算你有@Autowired这个注解,它也不知道从哪里注入数据,所以就会有这个异常。
问题原因分析出来后,我们就想,能不能自己提供一个IOC容器呢,即
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
往往在现实开发中,软件开发和软件测试是两个职位,上述代码如果是开发编写的话,往往没什么问题。但测试人员可能会不懂Spring的代码,所以需要另外一种办法,好在Spring为我们提供了整合Junit的使用。
- 首先引入Spring-test的jar坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
<scope>test</scope>
</dependency>
Spring给我们提供了一个main方法,这个main方法支持Spring框架,我们用这个main替换Junit的main方法。
@RunWith(SpringJUnit4ClassRunner.class)
- 在类上加上这个注解,@Runwith代表要替换的运行器,后面在字节码参数
- 告诉Spring配置文件/配置类的位置
@ContextConfiguration(locations = "classpath:bean.xml")
使用Contextfiguration注解可以完成该功能,locations表示配置文件的位置,加上classpath表示类路径。
至此整合结束,测试方法直接使用既可,但是这里有个版本问题,如果你使用的是Spring5.0以上的话,你的Junit版本必须是4.12以上!!!
不然会曝出错误
java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
注解说明:
@RunWith:用于指定junit运行环境,是junit提供给其他框架测试环境接口扩展,为了便于使用spring的依赖注入,spring提供了org.springframework.test.context.junit4.SpringJUnit4ClassRunner作为Junit测试环境
@ContextConfiguration({“classpath:applicationContext.xml”,“classpath:spring/buyer/applicationContext-service.xml”})
导入配置文件,这里我的applicationContext配置文件是根据模块来分类的。如果有多个模块就引入多个“applicationContext-service.xml”文件。如果所有的都是写在“applicationContext.xml”中则这样导入:
@ContextConfiguration(locations = “classpath:applicationContext.xml”)@Rollback 和 transactionManager @Rollback(新增注解)代替,其中只有一个属性就是boolean型的value,作用没变,值为true表示测试时如果涉及了数据库的操作,那么测试完成后,该操作会回滚,也就是不会改变数据库内容;值为false则与此相反,表示你测试的内容中对数据库的操作会真实的执行到数据库中,不会回滚。
单元测试中setUp方法和setUpBeforeClass方法的区别
setUp方法原来是每个方法测试之前都会调用一次,而setUpBeforeClass则在整个类测试过程中只调用一次。同理,tearDown和tearDownAfterClass的方法也是在于此。setUpBeforeClass和tearDownAfterClass这两个方法是在junit4中新增的,junit3中没有。
创建基本单元测试类的目的是在父类加载了spring等配置文件,子类不需要再次加载,减少重复操作