web-dev-qa-db-ja.com

@InjectMocksクラスのメソッドをモックするにはどうすればよいですか?

たとえば、ハンドラーがあります。

_@Component
public class MyHandler {

  @AutoWired
  private MyDependency myDependency;

  public int someMethod() {
    ...
    return anotherMethod();
  }

  public int anotherMethod() {...}
}
_

それをテストするために、私はこのような何かを書きたいです:

_@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @InjectMocks
  private MyHandler myHandler;

  @Mock
  private MyDependency myDependency;

  @Test
  public void testSomeMethod() {
    when(myHandler.anotherMethod()).thenReturn(1);
    assertEquals(myHandler.someMethod() == 1);
  }
}
_

しかし、実際にそれをモックしようとすると、anotherMethod()を呼び出します。 myHandlerでメソッドをモックするにはどうすればよいですか?

46
Vova Yatsyk

まず、MyHandlerメソッドをモックする理由は次のとおりです。すでにanotherMethod()をテストしており、複雑なロジックを持っているので、なぜ(someMethod()の一部のように)呼び出している_verifyだけができたら?
次の方法で対応できます。

@RunWith(MockitoJUnitRunner.class}
class MyHandlerTest {

  @Spy  
  @InjectMocks  
  private MyHandler myHandler;  

  @Mock  
  private MyDependency myDependency;  

  @Test  
  public void testSomeMethod() {  
    doReturn(1).when(myHandler).anotherMethod();  
    assertEquals(myHandler.someMethod() == 1);  
    verify(myHandler, times(1)).anotherMethod();  
  }  
}  

注:「スパイ」オブジェクトの場合、doReturnの代わりにthenReturnを使用する必要があります(ほとんど説明はありません here

85
Vova Yatsyk

コードでは、MyHandlerをまったくテストしていません。テスト対象をモックしたくない、実際のメソッドを呼び出したい。 MyHandlerに依存関係がある場合、それらをモックします。

このようなもの:

public interface MyDependency {
  public int otherMethod();
}

public class MyHandler {
  @AutoWired
  private MyDependency myDependency;

  public void someMethod() {
    myDependency.otherMethod();
  }
}

そしてテスト中:

private MyDependency mockDependency;
private MyHandler realHandler;

@Before
public void setup() {
   mockDependency = Mockito.mock(MyDependency.class);
   realHandler = new MyHandler();
   realhandler.setDependency(mockDependency); //but you might Springify this 
}

@Test
public void testSomeMethod() {

  //specify behaviour of mock
  when(mockDependency.otherMethod()).thenReturn(1);

  //really call the method under test
  realHandler.someMethod();
}

重要なのは、テスト対象のメソッドを実際に呼び出すことですが、それらが持つ可能性のある依存関係を模倣することです(他のクラスのメソッドの呼び出しなど)

これらの他のクラスがアプリケーションの一部である場合、独自の単体テストがあります。

[〜#〜] note [〜#〜]上記のコードはより多くの注釈で短縮できますが、説明のためにもっと明示的にしたかったのです注釈は:))

0
NickJ