私は今日だけMockitoについて学び始めました。簡単なテストを作成しましたが(JUnitを使用、以下を参照)、SpringのマネージドBean内でモックオブジェクトを使用する方法がわかりません。Springを使用するためのベストプラクティスは何ですか。Beanにモックされた依存関係をどのように注入する必要がありますか?
私の質問に戻るまでこれをスキップできます。
まず第一に、私が学んだこと。これは、基本を説明する非常に優れた記事Mocks Are n't Stubsです(Mockは、状態の検証ではなく、動作の検証をチェックします)。次に、ここにMockito と、ここにmockitoを使用したより簡単なモックの良い例があります。Mockitoのモックオブジェクトはモックとスタブの両方であるという説明があります。
ここMockitoとここMatchers、あなたはより多くの例を見つけることができます。
このテスト
@Test
public void testReal(){
List<String> mockedList = mock(List.class);
//stubbing
//when(mockedList.get(0)).thenReturn("first");
mockedList.get(anyInt());
OngoingStubbing<String> stub= when(null);
stub.thenReturn("first");
//String res = mockedList.get(0);
//System.out.println(res);
//you can also verify using argument matcher
//verify(mockedList).get(anyInt());
verify(mockedList);
mockedList.get(anyInt());
}
うまく動作します。
私の質問に戻ります。ここでは、誰かがSpringを使用しようとするSpring BeanにMockitoモックを注入ReflectionTestUtils.setField()
しますが、ここでは、Spring統合テスト、モックオブジェクトの作成で、 Springのコンテキストを変更することをお勧めします。
最後の2つのリンクがよくわかりませんでした...SpringがMockitoでどのような問題を抱えているのか、誰かに説明してもらえますか?このソリューションの何が問題になっていますか?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
編集:私は本当に明確ではありませんでした。自分自身を明確にするために、コードの3つの例を示します。HelloWorldのメソッドへの呼び出しを転送するメソッドをprintHello()
持つBeanHelloWorldとメソッドを持つBeanHelloFacadeがあるとします。sayHello
printHello()
最初の例は、Springのコンテキストを使用し、カスタムランナーを使用せずに、依存性注入(DI)にReflectionTestUtilsを使用することです。
public class Hello1Test {
private ApplicationContext ctx;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}
@Test
public void testHelloFacade() {
HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
HelloWorld mock = mock(HelloWorld.class);
doNothing().when(mock).printHello();
ReflectionTestUtils.setField(obj, "hello", mock);
obj.sayHello();
verify(mock, times(1)).printHello();
}
}
@Noamが指摘したように、を明示的に呼び出さずに実行する方法がありますMockitoAnnotations.initMocks(this);
。また、この例ではSpringのコンテキストの使用をやめます。
@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {
@InjectMocks
private HelloFacade obj = new HelloFacadeImpl();
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
これを行う別の方法
public class Hello1aTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@InjectMocks
private HelloFacadeImpl obj;
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
いいえ、前の例では、HelloFacadeImplを手動でインスタンス化して、HelloFacadeに割り当てる必要があります。これは、HelloFacadeがインターフェイスであるためです。最後の例では、HelloFacadeImplを宣言するだけで、Mokitoがそれをインスタンス化します。このアプローチの欠点は、現在、テスト対象のユニットがimplクラスであり、インターフェイスではないことです。