私のコード:
@Component
public class A {
@Autowired
private B b;
public void method() {}
}
public interface X {...}
@Component
public class B implements X {
...
}
クラスAを分離してテストしたいのですが、クラスBをモックする必要がありますか?はいの場合、どのように?それは自動配線されており、モックされたオブジェクトを送信できるセッターがないためです。
分離クラスAでテストしたい.
Bのインスタンスをインスタンス化して注入するのではなく、絶対にBをモックする必要があります。ポイントは、Bが機能するかどうかをテストすることです。
そうは言っても、 Mockito を強くお勧めします。モックフレームワークが進むにつれて、非常に使いやすくなります。次のように記述します。
@Test
public void testA() {
A a = new A();
B b = Mockito.mock(B.class); // create a mock of B
Mockito.when(b.getMeaningOfLife()).thenReturn(42); // define mocked behavior of b
ReflectionTestUtils.setField(a, "b", b); // inject b into the B attribute of A
a.method();
// call whatever asserts you need here
}
Spring 3.1、JUnit 4.7、およびMockito 1.9でテストを動作させる方法の例を次に示します。
FooService.Java
public class FooService {
@Autowired private FooDAO fooDAO;
public Foo find(Long id) {
return fooDAO.findById(id);
}
}
FooDAO.Java
public class FooDAO {
public Foo findById(Long id) {
/* implementation */
}
}
FooServiceTest.Java
@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
@Mock private FooDAO mockFooDAO;
@InjectMocks private FooService fooService = new FooService();
@Test public final void findAll() {
Foo foo = new Foo(1L);
when(mockFooDAO.findById(foo.getId()).thenReturn(foo);
Foo found = fooService.findById(foo.getId());
assertEquals(foo, found);
}
}
SpringのReflectionTestUtils.setField
(またはjunit拡張PrivateAccessor
)を使用してリフレクションを介してフィールドを注入するか、模擬アプリケーションコンテキストを作成してロードできます。単純なユニット(非統合)テストの場合、単純化のためにリフレクションを使用することをお勧めします。
このフォーラムのディスカッション 私には理にかなっています。クラスBによって実装されるInterfaceBのタイプ(つまり、サービス指向)としてプライベートメンバーbを宣言してから、MockBクラスも同じインターフェイスを実装すると宣言できます。テスト環境のアプリケーションコンテキストで、MockBクラスを宣言し、本番アプリケーションコンテキストで通常のBクラスを宣言します。どちらの場合でも、クラスAのコードは自動配線されるため、変更する必要はありません。