2017-09-06 10 views
3

한다고 가정 내가 가진 클래스를 조롱 :캡슐화 및 간단한 의존성과

public interface Dependency { 
    int doSomething(int value); 
    void doMore(int value); 
    int doALotMore(int value); 
} 

public final class A implements SomeInterface { 
    private final Dependency dep; 

    public A (Dependency dep) { 
     this.dep = dep; 
    } 

    @Override 
    public int add(final int x) { 
     dep.doMore(x); 
     return x + dep.doSomething(x) + dep.doALotMore(x); 
    } 
} 

을 내가 쓰고 있어요 테스트를 사용하여 망신 시켰습니다 : 지금까지

public class TestA { 
    private Dependency mockDep; 
    private SomeInterface a; 

    @Before 
    public void setUp() { 
     mockDep = Mockito.mock(Dependency.class); 
     a = new A(mockDep); 
    } 

    @Test 
    public void shouldAdd() { 
     final int x = 5; 
     when(mockDep.doSomething(x)).thenReturn(6); 
     when(mockDep.doALotMore(x)).thenReturn(7); 

     int actual = a.add(x); 

     assertThat(actual, is(18)); 

     verify(mockDep, times(1)).doSomething(); 
     verify(mockDep, times(1)).doALotMore(); 
     verify(mockDep, times(1)).doMore(); 

     verifyNoMoreInteractions(mockDep); 
    } 
} 

너무 좋아.

그래서 질문은 : 우리는 의존성이 어떻게 사용되었는지 정확히 확인하여 클래스 A의 캡슐화를 위반합니까? 의존성이 정확히 그렇게 사용되었는지 테스트해야 할 필요가 있습니까? A을 블랙 박스처럼 테스트하면 안됩니다 (테스트 케이스에서 verify 호출을 삭제하고 단지 assertThat으로 두십시오)? 그리고 이런 경우 종속성을 어떻게 다룰 것인가?

내가 부탁 해요 이유는 내가 자신을 검증 의존성 코드의 좋은 금액을 작성하고 우리가 클래스에 대한 실제 내부 구현 세부 사항을 테스트하기 시작하는 것 같다 잡은 것입니다. 그리고 저는이 구현 세부 사항을 다른 방법으로 다시 작성하려고 할 때 예를 들어 add의 결과가 같지만 테스트 사례를 다시 작성해야하기 때문에 그 점에 대해 불편합니다. 클래스를 검정 상자로 테스트하면 구현 세부 사항을 변경할 수 있으며 주어진 입력이 동일한 출력을 제공하는지 확인할 수 있습니다.

아니면 실제로 정확하게 구현 세부 사항을 테스트 할 필요하며, 그 단위 테스트 자체의 포인트입니다? 나를 위해 다소 틀린 것 같습니다. 정말 당신이 테스트하고 논리에 따라

public class TestA { 
    private Dependency mockDep; 
    private SomeInterface a; 
    private final int x = 5; 

    @Before 
    public void setUp() { 
     mockDep = Mockito.mock(Dependency.class); 
     a = new A(mockDep); 

     when(mockDep.doSomething(x)).thenReturn(6); 
     when(mockDep.doALotMore(x)).thenReturn(7); 
    } 

    @Test 
    public void shouldAdd() { 
     int actual = a.add(x); 

     assertThat(actual, is(18)); 
    } 
} 
+0

A # 애드 (INT)가'로 특정 메소드 호출의 결과를 추가하는 방법으로 정의된다'경우 잘 때'자체 x', 실제로이 방법을 호출하고, X '에 추가하는 것이 테스트 '. _When_ 및 _where_'add' 호출은 종속 클래스의 메소드는 실제로 테스트에 중요하지 않으며 어쨌든 테스트하지 않습니다 (여기의 예제에서). 따라서 그 테스트는 나에게 잘 보입니다. 테스트 케이스 중 하나에 불쾌감을 느끼는 예가 있습니까? ('verifyNoMoreInteractions (mockDep);의 사용법은 논쟁의 대상이 될 수는 없지만 테스트 된 주제에 달려있다.) – Tom

+1

단위 테스트는 회색/흰색 상자 테스트입니다. 블랙 박스 테스트로 사용해서는 안됩니다. 이 클래스의 목적은 클래스의 종속성과 상호 작용하는 방법을 포함하여 테스트에서 클래스의 모든 논리를 테스트하는 것입니다. 가짜는 의존성 코드 테스트를 피하는 데 도움이됩니다. – tsolakp

+0

일반적으로 상호 작용을 확인하거나 통화를 스텁하고자합니다. 일반적으로 두 가지 일을하는 것은 나쁜 징조입니다. 이 경우 예를 들어, 비헤이비어를 스텁하고자합니다. 귀하의 모의이 호출되지 않으면 대답이 잘못 될 수 있습니다. 스텁이 호출되었는지 확인할 필요가 없습니다. 다른 상호 작용이 발생하지 않도록하려면 엄격 모드 (https://static.javadoc.io/org.mockito/mockito-core/2.9.0/org/mockito/Mockito.html##)를 사용 설정하는 것이 좋습니다. 40). –

답변

3

:

대신이 테스트를 고려하십시오. 귀하의 예를 들어 어떤 컨텍스트를 제공하지 않기 때문에 내가하지 이러한 상호 작용을 테스트 할 경우에만 편안하지만도 필수 느낄 때, 나는 당신에게 케이스를주지 :

이의 당신이 인증 토큰 유효성 검사를 테스트하고 있다고 가정 해 봅시다. 유효성 검사기에 토큰을 보내면 true/ false이 반환됩니다. 유효성 검사기 내부에서 jwt.validate 또는 다른 제 3 자 해시 검증 방법을 호출 중입니다. 이 경우에는이 유효성 검사기를 무시하고 false를 반환하는 if token == null 조건을 도입 할 수 있기 때문에이 유효성 검사기가 매번 호출된다는 것을 알아야합니다. 그렇다면 테스트는 계속 될 수 있지만 코드는 이제 타이밍 공격에 취약합니다.

그것은 예를 들어 한 종류입니다. 그런 방식으로 테스트 할 수있는 다른 유형의 테스트는 border testing입니다. 클래스가 스트라이프 지불 게이트웨이를 트리거한다는 것을 알고 싶습니다. 따라서이 테스트에서 정교하게 검사하지 않고 호출합니다.