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;
    }
}

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