• 참고 URL
    • https://code.google.com/p/powermock/wiki/MockitoUsage13
    • http://stackoverflow.com/questions/11458963/mockito-0-matchers-expected-1-recorded-invaliduseofmatchersexception

단위테스트를 작성하다보면 환경에 따라 다르게 동작하거나 static method 로 인해 특정 케이스를 재현하기 어려운 경우가 존재한다.
단위테스트는 환경에 영향받지 않고 어떤 환경이든 해당 단위(메소드 또는 기능)에 대해 의도한 대로 로직이 구현되어있음을 확인하는것으로
이러한 경우에 Mock 객체를 활용하여 단위테스트를 구성할 수 있다.

일반적인 object의 method에 대해서는 왠만한 사람들이라면 Easymock, Mockito, Powermock 등 다양한 라이브러리를 통해 테스트케이스를 생성한다.
하지만 static method나 private method에 대해서는 일반적인 mock 생성을 통해 조작이 불가하며 reflection을 통해 객체를 가로채어 바꾸어주어야 한다.

예전에는 Whitebox 라는 메소드인지 클래스인지..를 통해서 private method에 대한 mocking을 설정했던것 같은데..
여기서는 Powermock을 통해 static method를 mock 처리하는 방법에 대해 정리하고자 한다.
+) 테스트를 작성하다 보니 transactionmanager.getTransaction()을 mocking 하는데 matcher도 규격대로 작성했건만 에러가 발생한다. 이 부분에 대해 추가정리!

STATIC METHOD Mocking

1.  library 준비

  • http://mvnrepository.com/artifact/org.powermock
    • powermock-module-junit : junit과 연동하기위한 dependency. Runner class가 들어있다.
    • powermock-api-mockito : Mock 처리를 위한 dependency. Powermockito class가 들어있다.
2. Test Case 에 적용.


@RunWith(PowerMockRunner.class)
@PrepareForTest(Static.class) // mock 처리하고싶은 static method를 보유한 class 
public class StaticMockingTest {
    private AAA mockAAA;

    @Test
    public void test() {
        // GIVEN
        // 일반적인 Mock 객체 생성 및 mock 처리
        this.mockAAA = PowerMockito.mock(AAA.class);
        PowerMockito.when(mockAAA.getValue("key")).thenReturn("value"); // case에 따라 matcher를 사용하여 범용처리를 하기도 한다.

        // static method Mock 처리
        PowerMockito.mockStatic(Static.class);
        
PowerMockito.when(Static.getInstance()).thenReturn(mockAAA); // static method가 호출되었을때에 대한 mock 처리
        // static mock 처리에는 Class 위에 선언된  @RunWith, @PrepareForTest annotation이 설정되어있어야만 정상 동작한다.

        // WHEN
       
Assert.assertEquals(mockStatic, Static.getInstance());

        // THEN
        PowerMockito.verifyStatic();
    }
}



FINAL METHOD Mocking

  • 참고 URL
    • http://stackoverflow.com/questions/11458963/mockito-0-matchers-expected-1-recorded-invaliduseofmatchersexception
    • http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/transaction/support/AbstractPlatformTransactionManager.html#getTransaction(org.springframework.transaction.TransactionDefinition)
    • http://docs.spring.io/spring-framework/docs/2.0.x/api/org/springframework/transaction/PlatformTransactionManager.html#getTransaction(org.springframework.transaction.TransactionDefinition)

 [Logic] - 메소드 내에 다음과 같은 로직이 들어있었다. 바꾸기는 부담스럽고(history를 알 수 없어서), 일단 테스트를 하려고보니...

 @Autowired // 사실은 spring version이 낮아 setter method 로 들어갔음.
 DataSourceTransactionManager transactionManager; 

 DefaultTransactionDefinition def = new DefaultTransactionDefinition();
 def.setName("transaction");
 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
 TransactionStatus status = transactionManager.getTransaction(def);

 [TEST] - transactionManager.getTransaction(def) 이 statement를 mocking 하기위해 다음과 같이 했더니 에러가 발생한다. ??

 when(mockTransactionManager.getTransaction(any(DefaultTransactionDefinition.class))).thenReturn(mockTransactionStatus);

 org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
      
Invalid use of argument matchers!
      
0 matchers expected, 1 recorded:
 
This exception may occur if matchers are combined with raw values:
      
//incorrect:
      
someMethod(anyObject(), "raw String");
 
When using matchers, all arguments have to be provided by matchers.
      
For example:
      //correct:
      
someMethod(anyObject(), eq("String by matcher"));      

 뭐가 문제인지 몰라 한참을 확인해보니.... 구현체의 메소드가 final로 선언되어 변경이 불가능한것이었다! 그래서..저런에러가..

  • transactionManager의 구현체인 DataSourceTransactionManager의 getTransaction 메소드는 final로 선언되어 mocking 불가
    (DataSourceTransactionManager가 상속한 AbstractPlatformTransactionManager 부터 getTransaction 메서드는 final로 선언되어있으며, final method를 mocking하기 위해서는 static method와 마찬가지로 설정해주어야 한다.)
 그래서인지 실제 로직에서는 인터페이스를 통해 구현체를 주입받도록 권고하나 보다..
 이 TransactionManager의 interface인 PlatformTransactionManager는 getTransaction 메서드가 public으로 선언되어있어 일반적인 방법으로도 충분히 mocking이 가능하다.











'myplace' 카테고리의 다른 글

Maven test와 junit의 동작 차이 (@Ignore annotation이 다르게 동작해요)  (0) 2015.05.14
SonarQube  (0) 2014.09.06
jenkins CI Server  (0) 2014.09.05
Posted by dreamhopp
,
  • 참고 URL :
    • http://junit.10954.n7.nabble.com/maven2-with-Junit-4-ignores-Test-annotations-td8629.html
    • http://maven.apache.org/surefire/maven-surefire-plugin/examples/junit.html
    • http://stackoverflow.com/questions/7535177/if-i-ignore-a-test-class-in-junit4-does-beforeclass-still-run

IDE에서 Junit4로 테스트시 @Ignore 등 annotation 정상동작함.
mvn clean compile test 명령어를 통해 Maven으로 test 수행시 @Ignore 등 annotation이 무시되어 Ignore처리된 테스트도 수행됨(결과는 failure로 잡힘)

원인은 못찾음. 뭔가 동일한 테스트 클래스가 존재한다는 말은 있지만..

해결방법은 @Ignore 처리한 Class를 maven 설정에서 exclude에 추가.

<build>설정에 다음내용 추가

<plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-surefire-plugin</artifactId>

                <version>2.8</version>

                <configuration>

                    <includes>

                        <include>**/*Test.java</include>

                    </includes>

                    <excludes>

                        <exclude>**/*DAOTest.java</exclude>

                    </excludes>

                </configuration>

                <dependencies>

                    <dependency>

                        <groupId>org.apache.maven.surefire</groupId>

                        <!-- Use the older JUnit 4 provider -->

                        <artifactId>surefire-junit4</artifactId>

                        <version>2.8</version>

                    </dependency>

                </dependencies>

            </plugin> 


'myplace' 카테고리의 다른 글

Static, Final Method Unit Test  (0) 2015.05.14
SonarQube  (0) 2014.09.06
jenkins CI Server  (0) 2014.09.05
Posted by dreamhopp
,

SonarQube

myplace 2014. 9. 6. 09:42

Jenkins CI Server 설정 중 알게된 Sonar에 대해 소개하려 한다.
Sonar는 소스를 분석하고 결함을 찾아주어 사용자에게 제공한다. 또한 다양한 플러그인을 통해 여러언어, 여러가지 분석 툴을 제공한다. 일부는 Jenkins와도 겹치는 분석이 있으나 하나의 툴로 여러가지 분석(LOC, DupCode, Static Code Analysis, cycle 등)을 제공한다는 점에서 편리하다 생각된다.
나는 Jenkins는 자동화된 build를 통한 CI를 유지하는 목적으로, SonarQube는 소스코드에대한 다양한 분석결과를 파악하는 용도로 사용하고있다.


SonarQube

SonarQube에 대한 자세한 설명은 다음의 홈페이지에서 잘 나와있다. (http://www.sonarqube.org/)
Sonar 분석을 사용하기 위해서는 먼저 2개의 tool이 필수로 설치되어야 한다. 설치를 위해서는 Download  페이지를 방문하면 된다.

 * SonarQube
   : Sonar 분석결과를 저장하고 사용자에게 노출한다. 확장된 플러그인을 통해 다양한 언어 및 타 tool의 분석결과를 SonarQube 상에서 지원한다.
 * Sonar-runner
   : Sonar 분석을 위한 도구로 maven, ant, command line, jenkins 등 다양한 환경에서 소스를 분석한다. Sonar-runner는 command line을 기본으로 지원하며 이 외의 방법으로 build를 위해서는 추가설정 및 라이브러리가 필요하다.
 * SonarQube Maven Plugin, SonarQube Ant Task
   : Maven, Ant 의 build를 위해 필요한 jar, document 를 제공한다.
 * Jenkins Sonar Plugin
   : Jenkins에서 제공하는 Sonar 분석을 지원하는 Plugin이다. SonarQube, Sonar-runner에 대한 설정을 [Jenkins관리 > 시스템설정]에 추가하고, [프로젝트 설정]에서 [build 후 step]에 Sonar를 추가하면 Maven 추가설정 없이 Maven을 통한 Sonar 분석이 수행된다.


Sonar Analysis

Sonar는 기본적으로 Java에 대한 분석을 제공하고있으며, 이외의 다양한 언어에 대해 함께 분석하려면 다음의 조건이 만족되어야 한다.
 - parameter에 sonar.language 값이 없어야 함.
 - SonarQube Update Center에서 다른 언어(CSS, C, Python 등)에 대한 Plugin 설치

SonarQube Update Center는 SonarQube 로그인(초기 계정/PW : admin/admin) 후 [settings] 를 통해 접근이 가능하다.
Update Center에서 설치하고자 하는 플러그인 선택 후 SonarQube를 재시작하면 선택한 플러그인 적용이 가능하다.
이외에도 settings 페이지를 통해 analysis exclude, rule, access 권한 설정 등 다양한 설정을 할 수 있다.


QnA

1. Web Project 분석을 위해 Web Plugin을 설치했는데 분석결과에 html만 표시되고 jsp에 대한 분석이 나오지 않는다?
 => [SonarQube > Settings > General Settings > Web Category] 에서 file suffixes값이 ".html,.xhtml,.rhtml,.shtm"이 기본값으로 설정되어있으므로 지원하는 확장자 중 원하는 파일 확장자를 ,(comma) 구분자를 통해 나열하면 해당파일에 대한 분석된 결과를 볼 수 있다.


SonarQube 참고자료 : 
홈페이지http://www.sonarqube.org/
Download
http://www.sonarqube.org/downloads/
Analysis Setting
http://docs.codehaus.org/display/SONAR/Analyzing+Source+Code
Analysis Parameter : http://docs.codehaus.org/display/SONAR/Analysis+Parameters
Plugin matrix
http://docs.codehaus.org/display/SONAR/Plugin+version+matrix
                 (matching 되는 버전이 아닌경우 SonarQube 서버 실행시 오류 발생함)


Posted by dreamhopp
,

jenkins CI Server

myplace 2014. 9. 5. 23:14

무언가를 시작하기 전에 이에대해 자동으로 빌드 및 코드 품질을 검증하고자 CI서버를 구축하였다.
(자주 사용했던) 쉽게 구축 가능한 Jenkins CI Server와 사용하기 유용한 plugin들을 정리한다.


Continuous Integration 란?

'지속적인 통합' 
지속적으로 소스코드, 테스트 및 빌드를 자동화하여 변경사항이 정상적으로 통합되었음을 검증한다.
대표적으로 Jenkins(구 Hudson)이 있으며 이러한 자동화 및 검증과정을 도와준다.
CI를 적용할 경우 변경사항이 정상인지 여부를 시스템에서 자동으로 통합과정을 통해 검증해주며, 실패한경우 메일과 같은 noti 수단을 통해 통보받을 수 있다. 이를 통해 통합 실패에 대해 빠르게 발견할 수 있으며 에러원인분석 및 수정에 대한 비용을 감소시킬 수 있다.


Jenkins CI Server

download url : http://jenkins-ci.org/
대표적인 CI tool로 다양한 plugin을 통해 검증도구를 제공한다.
기존에는 Hudson이라는 이름으로 제공되었으나 Oracle에서 상표등록하여 이의를 제기하면서 Jenkins로 이름을 변경하였다.
기본적으로 계정관리 및 자동화된 빌드를 제공하며 플러그인 설치 및 적용을 통해 여러가지 분석 및 품질검증이 가능하다.


Plugins

[Jenkins관리 > 플러그인 관리] 메뉴에서 설치된 플러그인 및 설치가능한 플러그인을 확인할 수 있다.
이밖에도 *.hpi 파일을 업로드하여 사용자가 수동으로 플러그인 설치가 가능하다.
플러그인은 대부분 Jenkins 내에서 분석결과를 화면에 노출하는 기능을 제공하며, 이를 분석하는 tool을 수동으로 설치하고 Jenkins 관리에서 설정하거나 필요한 library를 추가해주어야 하는 경우가 많다.
아래는 내가 써 보았던 툴 중심으로 분류하였으며 이밖에도 Jenkins update center 의 설명을 보고 쉽게 플러그인이 제공하는 기능에 대해 파악 및 설치가 가능하다.

* SCM tool : Git, Subversion 등
* 정적코드 분석 tool : PMD, findbugs, klocwork, Sonar
* 중복코드 분석 tool : CPD (Dry plugin), Sonar
* Code Style Check tool : checkstyle
* Test Coverage tool : JaCoCo, Clover, Cobetur

* LoC Analysis tool : SLOCCount, CLOC, Sonar



참고자료 : 

Continues Integration with Hudson
http://doortts.tistory.com/entry/%EB%B2%88%EC%97%AD-%ED%86%B5%ED%95%A9-%ED%97%88%EB%93%9C%EC%8A%A8%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EC%A7%80%EC%86%8D%EC%A0%81%EC%9D%B8-%ED%86%B5%ED%95%A9-Continuous-integration-with-Hudson

'Hudson'에서 'Jenkins'로 변경된 이유
http://en.wikipedia.org/wiki/Hudson_(software)

'myplace' 카테고리의 다른 글

Static, Final Method Unit Test  (0) 2015.05.14
Maven test와 junit의 동작 차이 (@Ignore annotation이 다르게 동작해요)  (0) 2015.05.14
SonarQube  (0) 2014.09.06
Posted by dreamhopp
,