Spring:06 IoC-Spring集成Junit

Spring集成Junit

首先说明一个问题:“测试”,测的是什么?

​ 其实是测“类”,测类中的属性、方法。 Spring中统一把java类称为Bean对象

Spring中,Bean对象都是由Spring容器进行创建的。因此,Spring中对于Bean对象的测试,必须得先获取Spring容器,再从容器中取得Bean对象。所以,这两个步骤的代码,是每一个测试类都必须要写的代码。

无论是XML配置,还是注解配置,都必须要写“获取 Spring容器、从容器取Bean对象”的代码,如:

public class SpringAnnotationTest {

    /**
     * Spring新注解的测试
     */
    @Test
    public void testSpringNewAnnotation() throws Exception {
        //获取Spring容器,并从容器中获取数据源
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfiguration.class);//必须指明主配置类的字节码文件
        DataSource dataSource = (DataSource) context.getBean("dataSource");

        //从数据源中获取连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);

        //dao、service的测试
        UserService userService = (UserService) context.getBean("userServiceImpl");
        userService.save();
    }

    /**
     * 原始注解测试,其中也用到了XML配置
     */
    @Test
    public void testSpringOriginAnnotation() {
        //获取Spring容器,并从中获取Bean对象
        String config = "applicationContext.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(config);
        UserService service = (UserService) context.getBean("UserServiceImpl");

        //调用对象中的方法
        service.save();
    }
}

每写一个测试都要重复“获取Spring容器、从容器中获取Bean对象”的步骤,这是需要优化的。Spring自然会提供优化的方案。

这个方案的思路是:将原始的Junit单元测试包,集成到Spring中去

1. 导入两个依赖:junit、spring-test

Spring提供了针对Spring做单元测试的解决方案,其依赖为spring-test

<!--Spring-test-->
<!--注意:spring5 及以上版本要求 junit 的版本必须是 4.12 及以上-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

Maven项目中,单元测试基于junit依赖进行。spring-test方案,同样也需要junit依赖的支持。

<!--Junit-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

2. 创建测试类:SpringJunitTest

在Maven项目的测试包中创建

package cn.leap.test;

/**
 * Author: Feiyue
 * Date: 2019/7/7 11:56
 * Desc: Spring集成Junit的测试
 */
public class SpringJunitTest {

}

3. 配置测试类(注解配置)

3.1 @Runwith:替换原来的运行期

@RunWith(SpringJUnit4ClassRunner.class)//指定新的运行器,由它来创建IoC容器
public class SpringJunitTest {

}

3.2 @ContextConfiguration:指定配置文件或配置类

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(value={"classpath:applicationContext.xml"})//针对XML配置文件
@ContextConfiguration(classes = {SpringConfiguration.class})//针对配置类
//@ContextConfiguration(classes = {DataSourceConfiguration.class})//针对配置类
public class SpringJunitTest {

}

SpringConfiguration主配置类,其中导入了DataSourceConfiguration配置类

3.3 @Autowired:注入需要测试的Bean对象

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})
public class SpringJunitTest {
    @Autowired
    private UserService userService;
}

@Autowired是按类型注入。所以,前提是Spring容器中已经有了一个UserService类型的Bean对象。

这就需要在UserService实现类中声明好一个Bean对象,而这正是要被测试的Bean对象。

@Service("userServiceImpl") //@Service 用于service层实例化Bean
public class UserServiceImpl implements UserService {

    /*@Autowired
    @Qualifier("userDao")*/
    @Resource(name="userDaoImpl")
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void save() {
        userDao.save();
    }
}

4. 编写测试方法,测试Bean对象

在测试类SpringJunitTest中编写测试方法

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})//针对配置类
public class SpringJunitTest {

    @Autowired
    private UserService userService;

    @Test
    public void test01(){
        userService.save();
    }
}

测试方法test01(),必须要用@Test这个单元测试注解进行配置,否则是运行不了的。

这也是spring-test需要junit支持的原因所在。

(spring-test是Spring集成Junit的一种解决方案,根本还是在Junit。)

运行结果

UserDaoImpl: save()............
John
com.mysql.jdbc.Driver

Service对象中又注入有Dao对象,这是在“Spring依赖注入”时就写好的测试代码。

分析总结

以上的步骤,看起来并没有简化Spring中的单元测试,反而搞得更复杂了。

再来看测试类的代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})//针对配置类
public class SpringJunitTest {

    @Autowired
    private UserService userService;

    @Test
    public void testUserService(){
        userService.save();
    }
}

上面代码是进行某一个Bean对象的测试。

之前的所有步骤相当于是在搭建SpringJunit测试的环境。----------这一点非常重要

当再需要对第2个、第3个…第n个Bean对象进行测试时,测试环境已经搭建好了,直接在测试环境中(SpringJunitTest类中)注入相应的Bean对象,并写相应的测试方法即可。

这才是SpringJunit简化Spring中单元测试的理念所在。

如下,再要对DataSource对象进行测试,直接在测试环境中注入Bean对象,并进行测试即可。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class})//针对配置类
public class SpringJunitTest {

    @Autowired
    private UserService userService;

    @Autowired
    private DataSource dataSource;

    @Test
    public void testUserService(){
        userService.save();
    }

    @Test
    public void testDataSource() throws SQLException {
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

测试方法的个数,看自己的需要。

问题:

​ 前面讲了“@Autowired是按类型注入。所以,前提是Spring容器中已经有了一个UserService类型的Bean对象。”那么,上面代码中注入的待测试对象DataSource对象,是在哪里存放到Spring容器中去的??

//步骤1:设定了主配置类
@ContextConfiguration(classes = {SpringConfiguration.class})//针对配置类
public class SpringJunitTest {
    
}


//步骤2:主配置类导入DataSourceConfiguration配置类
@Configuration//声明该类为Spring核心配置类
@ComponentScan("cn.leap")//指定进行组件扫描的包
@Import({DataSourceConfiguration.class})//导入其他配置类
public class SpringConfiguration {

}

//步骤3:DataSourceConfiguration配置类配置了Bean对象
@PropertySource("classpath:jdbc.properties")//加载配置文件
public class DataSourceConfiguration {

    @Bean(name = "dataSource")//指示Spring将当前方法的返回值以指定名称放到Spring容器中
    public DataSource getDataSource() throws Exception {
        //获取连接池对象
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass(driver);
        ds.setJdbcUrl(url);
        ds.setUser(username);
        ds.setPassword(password);
        //返回DataSource对象
        return ds;
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章