2016-07-21 8 views
2

私は、春の起動アプリケーションでautowiredクラスのサービスを、テスト用に作成したクラスの擬似実装に置き換えたいと思っています。@InjectMocksを使用して@Autowiredフィールドを模擬実装に置き換えよう

私は、このクラスの動作が複雑すぎて、複数のモックそのものを必要とするため、mockitoを使用して模擬することができないため、作成しました。

私はこの模擬実装をサービスに注入する方法を考え出すことができません。ここで

は、状況の最小限の例です。

@Service 
public class ServiceIWantToTestImpl implements ServiceIWantToTest{ 

    @Autowired 
    ComplicatedDependency complicatedDependency; 

    @Override 
    public void methodUsingDependency(){ 
     String string = complicatedDependency.doSomething(); 
     System.out.println(string); 
    } 

} 


public class MockComplicatedDependency implements ComplicatedDepencency{ 

    public MockComplicatedDependency(...){ 
     // Inject other mocked objects into this mock 
    } 

    public String doSomthing(){ 
     // This would be a mocked version of this function for testing 
     return "test"; 
    } 

} 

@RunWith(MockitoJUnitRunner.class) 
public class TestingTheService(){ 
    @InjectMock 
    private static ServiceIWantToTest serviceIWantToTest = new ServiceIWantToTestImpl(); 

    @Mock 
    ComplicatedDependency mockComplicatedDependency; 

    @BeforeClass 
    public static void init(){ 
     mockComplicatedDependency = new MockComplicatedDependency(...); 
    } 

    @Test 
    public void testAttempt(){ 
     serviceIWantToTest.methodUsingDependency(); // This method calls complicatedDependency.doSomething() which does not run the mocked version in MockComplicatedDependency which I wanted to inject, and would always return null instead of the "test" string I put in this example. 
    } 

} 

答えて

4

あなたは、テスト中のクラスのためのセットアップの依存関係にMockitoの注釈を使用する必要がありますか?

それは単なる簡単なセットアップを行うと、ComplicatedDependencyフィールドにServiceIWantToTestImplクラスのコンストラクタやセッターを導入し、ComplicatedDependencyあなたのどんなIMPLに直接テスト・セットアップに依存関係を設定していない理由をメイン制約されていない場合例:

@Service 
public class ServiceIWantToTestImpl implements ServiceIWantToTest { 

    @Autowired 
    ComplicatedDependency complicatedDependency; 

    public ServiceIWantToTestImpl() { 

    } 

    public ServiceIWantToTestImpl(ComplicatedDependency complicatedDependency) { 
     this.complicatedDependency = complicatedDependency; 
    } 

    @Override 
    public void methodUsingDependency(){ 
     String string = complicatedDependency.doSomething(); 
     System.out.println(string); 
    } 
} 

public class TestingTheService { 

    private static ServiceIWantToTestImpl serviceIWantToTest; 

    @BeforeClass 
    public static void init(){ 
     serviceIWantToTest = new ServiceIWantToTestImpl(new MockComplicatedDependency()); 
    } 

    @Test 
    public void testAttempt() { 
     serviceIWantToTest.methodUsingDependency(); 
    } 

} 

これは一方向です。これはハックのビットですが

@RunWith(MockitoJUnitRunner.class) 
public class TestingTheService { 

    @InjectMocks 
    private static ServiceIWantToTestImpl serviceIWantToTest = new ServiceIWantToTestImpl(); 

    @Spy 
    private static ComplicatedDependency complicatedDependency = new MockComplicatedDependency(); 

    @BeforeClass 
    public static void init() { 

    } 

    @Test 
    public void testAttempt() { 
     serviceIWantToTest.methodUsingDependency(); 
    } 

} 

:あなたははこのよう@Spy代わりの@Mockを使用することができ

それはMockitoで動作させるために、。 @SpyアノテーションのJavaDocを読んで、あなたのテストに本当に必要なものが使用されていることを確認することを強くお勧めします。

+0

あなたが提案したように@Spyを使ってみましたが、うまくいきました。ありがとう!私は実際にテストのためだけにコンストラクタを導入したいとは思っていません、私は春にアプリケーションの依存性注入を処理させたいと思います。 –

+2

実際には、コンストラクタレベルの注入が推奨されています。フィールドレベルの注入は一般的にお勧めしません。 –

+1

@Milosが述べたように、Springはコンストラクタインジェクションを10年前から推薦しています。http://spring.io/blog/2007/07/11 /セッター注入対コンストラクター注入/使用必須/誰もフィールドインジェクションを使わなくてはなりません。 – jhyot

関連する問題