web-dev-qa-db-ja.com

spring 3自動配線とjunitテスト

私のコード:

@Component
public class A {
    @Autowired
    private B b;

    public void method() {}
}

public interface X {...}

@Component
public class B implements X {
    ...
}

クラスAを分離してテストしたいのですが、クラスBをモックする必要がありますか?はいの場合、どのように?それは自動配線されており、モックされたオブジェクトを送信できるセッターがないためです。

44
mike27

分離クラス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
}
83
earldouglas

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);
    }
}
18
Mike Partridge

SpringのReflectionTestUtils.setField(またはjunit拡張PrivateAccessor)を使用してリフレクションを介してフィールドを注入するか、模擬アプリケーションコンテキストを作成してロードできます。単純なユニット(非統合)テストの場合、単純化のためにリフレクションを使用することをお勧めします。

15
Jeff Storey

このフォーラムのディスカッション 私には理にかなっています。クラスBによって実装されるInterfaceBのタイプ(つまり、サービス指向)としてプライベートメンバーbを宣言してから、MockBクラスも同じインターフェイスを実装すると宣言できます。テスト環境のアプリケーションコンテキストで、MockBクラスを宣言し、本番アプリケーションコンテキストで通常のBクラスを宣言します。どちらの場合でも、クラスAのコードは自動配線されるため、変更する必要はありません。

0
Aaron