2012-03-21 2 views
25

@Autowired라고 표시된 여러 필드가있는 클래스에 대한 Unit 테스트를 작성하려고합니다. Spring이이 필드에 대한 구체적인 구현을 자동으로 해결한다는 사실을 감안할 때, EasyMock을 통해 생성 된 Mock 객체를 테스트 실행 중 종속성으로 연결하는 방법을 찾는 데 어려움을 겪고있다. 클래스에서 @Autowired를 사용한다는 것은 해당 클래스에 setter가 없다는 것을 의미합니다. 클래스에 추가 setter를 만들지 않고 mock 객체를 연결하는 방법이 있습니까?Junit과 EasyMock을 사용하여 자동 표기법을 사용하여 클래스 테스트를합니까?

public class MyTestClassForSomeClassUnderTest{ 
    private SomeType someType; 
    private SomeOtherType someOtherType; 

    @Before 
    public void testSetUp(){ 
    SomeClassUnderTest someClassToTest = new SomeClassUnderTest(); 
    someType = EasyMock.createMock(SomeType.class); 
    someOtherType = EasyMock.createMock(SomeOtherType.class); 
    //How to set dependencies???? 
    } 

    @Test 
    public void TestSomeMethodIWouldLikeToTest(){ 
    //?????? 
    } 

} 

는을 얻을 좋을 것이다 : 나는 벽에 충돌하기 전에

다음
public class SomeClassUnderTest implements SomeOtherClass{ 

@Autowired 
private SomeType someType; 

@Autowired 
private SomeOtherType someOtherType; 

@Override 
public SomeReturnType someMethodIWouldLikeToTest(){ 
//Uses someType and someOtherType and returns SomeReturnType 
} 

} 

가 내 테스트 클래스를 공예하고 어떻게 : 여기

내가 달성하기 위해 노력하고 있습니다 무엇의 예 올바른 방향으로 밀기.

감사

답변

34

당신은 반 성적, ReflectionTestUtils 예를 사용하여 필드에 직접 종속성을 삽입 할 수

ReflectionTestUtils.setField(testInstance, "fieldName", fieldValue); 

일부는 시험으로 만 사용, 어쨌든 클래스에 패키지 볼 수 setter 메소드를 추가하는 것이 바람직하다고 주장 할 것이다. 또는 autowired 필드가 아닌 autowired 생성자를 사용하고 테스트 종속성을 그 필드에 주입합니다.

+0

감사합니다. –

+1

http://stackoverflow.com/questions/16426323/injecting-into-autowired-variable-during-testing – Dan

+0

EasyMock은 모의 주입을 위해 Mockito와 유사한 3.2 버전의 주석을 지원합니다. 내 대답을 보라. – krm

6

리플렉션을 통해이 필드를 설정할 수도 있지만, 개발 도구가이 필드의 사용법을 찾지 못하게하고 나중에 SomeClassToTest을 리팩터링하는 것이 어렵게 만듭니다.

이러한 입력란에 공개 설정자를 추가하고 대신 @Autowired 특수 효과를 추가하는 것이 좋습니다. 이것은 반사를 피할뿐만 아니라 클래스의 외부 인터페이스를 명확히하고 유닛 테스트가이 인터페이스 만 사용하도록합니다. 나는 SomeClassToTest이 이미 SomeOtherClass 인터페이스를 구현하고 있으며, SomeClassToTest의 클라이언트는이 인터페이스 만 사용한다고 가정하므로 설정자를 SomeClassToTest에 공개하는 데 약간의 위험이 따릅니다.

더 나은 방법은 생성자 주입을 사용하고 필드를 final로 만드는 것입니다. 생성자 인수에 여전히 @Autowired을 사용할 수 있습니다.

1

답변을 수락하지 않았습니다. 즉, 자신 만의 리플렉션을 사용하는 것 (조롱 한 프레임 워크없이)은 권장하지 않습니다.

EasyMock의 3.2 버전부터는 mock을 정의하고 테스트중인 클래스에 주입하기 위해 주석을 사용할 수 있습니다. 그것을 수행하는 방법에 대한 자세한 설명은 EasyMock에의 공식 문서에서 찾을 수 있습니다 http://easymock.org/user-guide.html#mocking-annotations

다음은 상기 사이트에서 예입니다 : 팁을위한

import static org.easymock.EasyMock.*; 
import org.easymock.EasyMockRunner; 
import org.easymock.TestSubject; 
import org.easymock.Mock; 
import org.junit.Test; 
import org.junit.runner.RunWith; 

@RunWith(EasyMockRunner.class) 
public class ExampleTest { 

    @TestSubject 
    private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2 

    @Mock 
    private Collaborator mock; // 1 

    @Test 
    public void testRemoveNonExistingDocument() { 
    replay(mock); 
    classUnderTest.removeDocument("Does not exist"); 
    } 
} 
관련 문제