1.问题分析

在前面的案例中,我们每测试一个业务层的函数就要重新创建对象并获取bean对象,毫无疑问这就造成了很多的重复代码。该如何解决这个问题呢?首先我们来看一下Junit实现测试的原理。

一个java程序的运行时需要依赖main方法的,因为它是程序的入口,但是在使用Junit对函数进行单元测试的时候我们并没有写main方法,这是因为Junit已经集成好了一个main方法,他会判断当前测试类中有哪些方法含有@Test注解。有该注解的方法会被main函数执行。执行可以通过反射来完成。并且,Spring是不知道我们有没有用Spring框架的。

如果我们能在main方法中创建好容器对象,然后将需要用到的bean对象按类型自动注入就可以了。虽然我们改不了Junit的代码,但是Spring已经为我们提供了一个增强型的Junit单元测试工具,有了它我们就能把Junit中不能加载容器的main方法替换掉。这个工具叫做:spring-test

2.解决步骤

2.1 导入Maven坐标

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.2.RELEASE</version>
</dependency>

2.2 替换main方法

使用Junit提供的一个注解@Runwith,将不能创建容器对象的main方法(运行器)替换掉。替换成Spring提供的。

@RunWith(SpringJUnit4ClassRunner.class)

括号里面必须提供一个类的字节码,并且该类要继承自Runner

2.3 提供配置文件

这一步需要告诉Spring的运行器,spring的Ioc容器创建是基于xml的还是基于注解的,并且要给出配置文件(类)的位置。指定的方式是使用@ContextConfiguration该注解的属性主要有俩:

  • locations:指定xml配置文件的位置,加上classpath关键字,表示在类路径下
  • classes:指定注解类所在的位置

这里我们使用的是注解进行配置的,所以我们使用classes:

@ContextConfiguration(classes = SpringConfiguration.class)

3.实现结果

这里贴出一个比较完成的结果代码:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class AccountServiceTest {

    @Autowired
    private AccountService as;

    @Test
    public void testFindAll() {
        //3.执行方法
        List<Account> accounts = as.findAllAccount();
        for(Account account : accounts){
            System.out.println(account);
        }
    }
}

4.注意事项

当我们使用Spring5.x版本的时候,要求Junit必须是4.12以上版本。