2018年4月27日 星期五

JUnit 4 整合 Spring 3/4/5


<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
    
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>3.2.18.RELEASE</version>
</dependency>
    
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>3.2.18.RELEASE</version>
    <scope>test</scope>
</dependency>
    
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>
    
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

※spring-web 使用在 spring web 時;spring-webmvc 使用在 spring mvc


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import bean.Apple;
import bean.Banana;
    
// @ContextConfiguration(locations = { "classpath*:/applicationContext.xml" })
@ContextConfiguration(classes = { Apple.class })
// @RunWith(SpringRunner.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class AppTest {
    @Autowired
    private Apple apple;
    
    @Autowired
    private Banana banana;
    
    @Test
    public void testSomeLibraryMethod() {
        System.out.println("apple=" + apple);
        System.out.println("banana=" + banana);
    }
}

※@RunWith 二選一

※@ContextConfiguration 有 locations 和 classes,看要用設定檔或是 Annotation

※測 web 或 mvc 時,有可能要抓 WEB-INF 的路徑,可用 ApplicationContext app = new FileSystemXmlApplicationContext("src/main/webapp/WEB-INF/applicationContext.xml");
和 @ContextConfiguration(locations = "file:src/main/webapp/WEB-INF/applicationContext.xml")



※spring-test 包的 annotation

必需加 @ContextConfiguration 和 @RunWith,不加也不會報錯,只是使用 spring 的 annotation時,一點效果都沒有而已


※@Repeat、@Timed、@IfProfileValue

@ContextConfiguration(locations = { "classpath*:/applicationContext.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class AppTest {
    @Repeat(3)
    @Test
    public void testRepeat() {
        System.out.println("yeah");
    }
    
    @Timed(millis = 1000L)
    @Test
    @Ignore
    public void testTimed() {
        try {
            System.out.println("yeah1");
            Thread.sleep(2000);
            System.out.println("yeah2");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("yeah3");
    }
    
    @IfProfileValue(name = "java.specification.version", values = "8")
    @Test
    @Ignore
    public void testIfProfileValue() {
        System.getProperties().list(System.out);
    }
}

※@Timed 官網有說在失敗之前會完成測試,我試的結果不管怎麼樣都會成功,可能就是這個原因吧!



※@ProfileValueSourceConfiguration

配合@IfProfileValue,沒有@ProfileValueSourceConfiguration,預設是 SystemProfileValueSource
參數給一個類別,這個類別要實作 ProfileValueSource 介面


public class MyPVS implements ProfileValueSource {
    @Override
    public String get(String key) {
        System.out.println("key=" + key);
        return System.getProperty(key);
    }
}
    
    
    
@ContextConfiguration(locations = { "classpath*:/applicationContext.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
@ProfileValueSourceConfiguration(MyPVS.class)
public class AppTest {
    @Test
    @IfProfileValue(name = "java.specification.version", values = "10")
    public void testXxx() {
        System.out.println("xxx");
    }
}

※get 方法返回值等於 @IfProfileValue 的 values 值就會執行



※@ActiveProfiles、@Profile

.@Profile 裡面寫個字串,每一個 class 都可以有一個 @Profile
.@ActiveProfiles 裡面也是寫字串,只有裡面的字串和 @Profile 裡的字串一樣,才會被加載

@Component
public class App {}
    
@Component
@Profile("dev")
public class Animal {}
    
@Component
@Profile("product")
public class Bird {}
    
    
    
@ContextConfiguration(classes = { App.class, Animal.class, Bird.class })
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("product")
public class AppTest {
    @Autowired(required = false)
    private App app;
    
    @Autowired(required = false)
    private Animal animal;
    
    @Autowired(required = false)
    private Bird bird;
    
    @Test
    public void testApp() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        for (String s : app.getBeanDefinitionNames()) {
            System.out.println(s);
        }
        app.close();
    
        System.out.println("app=" + this.app);
        System.out.println("animal=" + animal);
        System.out.println("bird=" + bird);
    }
}

※使用 ClassPathXmlApplication 只能抓沒有 @Profile 的 App

※寫在 AppTest 的全域變數才是 @ActiveProfiles 參數裡有對應到 @Profile 參數才能抓到的 bean

※還是要加 @ContextConfiguration 和 @RunWith,否則三個全域變數都是 null

沒有留言:

張貼留言