IT/개발 기록

[Spring] Junit을 사용하여 단위테스트(Spring-Test사용)

JJo 2018. 11. 5. 17:38


Junit을 사용하여 단위테스트(Spring-Test사용)



Junit이란?

Java에서 독립된 단위테스트를 지원해주는 프레임워크


Spring-Test란?

@RunWith/@ContextConfiguration 등의 어노테이션을 활용하여

Spring Framework에서 조금 더 편하게 테스트를 지원할 수 있게 해준다




환경구성



*풀소스 : https://github.com/devJJo/Junit-Spring


1. Junit 라이브러리 추가


1-1. Add Library선택



1.2 JUnit선택 후 next




2. pom.xml 필요한 라이브러리 추가


- spring-test추가


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>SpringJunitTest</groupId>
    <artifactId>SpringJunitTest</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <warSourceDirectory>WebContent</warSourceDirectory>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.20.RELEASE</version>
        </dependency>
 
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.20.RELEASE</version>
        </dependency>
    </dependencies>
</project>
cs



3. spring을 활용함으로 xml설정파일 셋팅


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
        
    <!-- properties file 정보 -->    
    <context:property-placeholder 
        location="classpath:properties/values.properties"  />
        
    <!-- @Component @Value @Autowired 어노테이션을 선언한 클래스들을 스캐닝을 하기 위한 설정     -->
    <context:component-scan base-package="devjjo.junit.dto" />
        
    <!-- StringPrinter 클래스를 bean으로 등록-->
    <bean id="stringPrinter" class="devjjo.junit.dto.before.StringPrinter" />
    
    <!-- ConsolPrinter 클래스를 bean으로 등록 -->
    <bean id="consolePrinter" class="devjjo.junit.dto.before.ConsolePrinter" />
    
    <!-- Hello 클래스를 bean으로 등록 첫번째방법 -->
    <bean id="helloPrinter" class="devjjo.junit.dto.before.Hello" >
        <!-- setter injection 설정 -->
        <property name="name" value ="조성훈"/>
        <property name="printer" ref ="stringPrinter"/>
    </bean>
    
    <!-- Hello 클래스를 bean으로 등록 두번째방법 -->
    <bean id="helloC" class="devjjo.junit.dto.before.Hello" >
        <!-- constructor injection 설정 -->
        <constructor-arg index="0" value="${name}"/>
        <constructor-arg index="1" ref="consolePrinter"/>
        <property name="names">
            <list>
                <value>${value1}</value>
                <value>${value2}</value>
                <value>${value3}</value>
            </list>
        </property
 
    </bean>
    
</beans>
 
 
cs


4. 테스트할 클래스 생성


- Hello.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package devjjo.junit.dto;
 
import java.util.List;
 
import javax.annotation.Resource;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
 
//Component 어노테이션 사용하면 xml에서 bean설정 해준느것과 같다 (EX:<bean id="stringPrinter" class =""> -> @Component)
@Component
public class Hello {
    
    // bean의 테스트 할 Value값 주는방식
    // 1. xml설정파일에 <property name="name" value ="조성훈"/> 과 같은 프로퍼티 설정 (이때, name맞춰줌)
    // 2. @Value("")로 어노테이션활용
    // 3. @Resource(name = "${sName}")로 properties설정파일 활용
    String name;
    
    // value의 값이 아니라 object를 넣어주는 방식
    // 1. @Autowired
    //      @Qualifier("stringPrinter") 해주면 partner빈 주입해주는것과 같다    
    // 2. @Resource(name = "${printer}") 활용
    Printer printer;
 
    public Hello() {
        System.out.println("Hello 기본 생성자 호출");
    }
 
    public Hello(String name, Printer printer) {
            System.out.println("Hello 오버로딩된 생성자");
        this.name = name;
        this.printer = printer;
    }
 
    public void setName(String name) {
        System.out.println("setNames 기본 생성자 호출 : " + name);
        this.name = name;
    }
 
    public void setPrinter(Printer printer) {
        System.out.println("setPrinter 기본 생성자 호출 : " + printer.getClass().getName());
        this.printer = printer;
    }
 
    public String sayHello() {
        return "Hello " + name;
    }
 
    public void print() {
        this.printer.print(sayHello());
    }
 
}
 
cs





- Printer.java

1
2
3
4
5
6
package devjjo.junit.dto;
 
public interface Printer {
    public void print(String message);
}
 
cs




- ConsolePrinter.java

1
2
3
4
5
6
7
8
9
10
11
package devjjo.junit.dto;
 
import org.springframework.stereotype.Component;
 
@Component("conPrinter")
public class ConsolePrinter implements Printer {
    public void print(String message) {
        System.out.println(message);
    }
}
 

cs



- StringPrinter.java

1
2
3
4
5
6
7
8
9
10
11
package devjjo.junit.dto;
 
import org.springframework.stereotype.Component;
 
@Component("conPrinter")
public class ConsolePrinter implements Printer {
    public void print(String message) {
        System.out.println(message);
    }
}
 
cs



- BeanSpringTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package devjjo.junit.test;
 
import java.util.List;
 
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
import devjjo.junit.dto.Hello;
import devjjo.junit.dto.Printer;
 
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:config/springbeans.xml")
public class BeanSpringTest {
    
    
    @Autowired
    @Qualifier("helloPrinter")
    Hello hello;
 
/*    @Autowired
    @Qualifier("helloC")
    Hello hello2;*/
    
    @Autowired
    @Qualifier("stringPrinter")
    Printer printer;
 
    @Test
    public void helloBean() {
        //값 비교 (Junit)
        Assert.assertEquals("Hello 조성훈", hello.sayHello());
 
        hello.print();
        Assert.assertEquals("Hello 조성훈", printer.toString());
    }
    
 
}
 
cs




목표



1.  BeanSpringTest.java를 Junit으로 실행하여 에러없이 초록불이 들어오면 된다. 초록불이 들어온다는건,  xml설정파일에서 주입한 값이 

Assert.assertEquals("Hello 조성훈", hello.sayHello());

이 부분에서 "Hello 조성훈"과 같다는 것이다.

Assert는 org.junit.Assert을 import하여 사용할 수 있는 함수로 값을 비교해준다





생각해 볼 부분



1. Junit Spring-test를 사용하는 이유?

controll, service, dao 단을 다 연결하고 main()함수에서 테스트를 진행할 때 

에러가 난다면 어디서부터 잘못 됐는지 확인해야될 부분이 많다, 화면에서 값이 잘못 넘어왔는지

서비스단 로직에서 잘못됐는지.. 또 여러명이 작업을 하고 합치는 경우에 자신이 만든 서비스 로직에 문제가 있는지

단위테스트를 하고자 할 때 Junit을 활용한다


2. Bean을 주입할 때 XML설정을 활용하는 방법과 소스에 Annotation을 활용하는 방법?

XML설정 파일을 활용하는 방법과 소스상에 Annotation을 달아 확인하는 방법 중 

진행하고있는 프로젝트에 맞게 적절히..활용해야 한다

예를 들어, 개발중에는 개발자 들 각각 Annotation방법을 사용하지만

실제 운영중에는 설정파일이 하나로 운영될 가능성이 높기 때문에 XML설정방법을 활용한다


3. XML이나 소스상 변하는값을 넣어줄 땐 properties파일을 활용하면 소스변경없이 (재컴파일 없이) 

사용할 수 있기 때문에 유연하다


4. 빈주입을 할 때 앞에 두글자는 소문자로 해야 자동으로 xml설정파일에서 인식한다


5. 사실.... 이런 단위테스트를 적용할 수 있는 환경이 아니라면 일을 위한 일을 하지 않는것이 좋을 것 같다.