7

springockito-annotations 1.0.9統合テストに使用しています。

私は次のコントローラーを持っています:

@Autowired
    public Controller(
            @Qualifier("passwordService ") PasswordService passwordService ,
            @Qualifier("validator") Validator validator,
            @Qualifier("reportService") ReportService reportService,
            DateCalculator dateCalculator,
            Accessor accessor){
        this.passwordService = passwordService;
        this.validator = validator;
        this.reportService = reportService;
        this.dateCalculator = dateCalculator;
        this.accessor = accessor;
    }

テストでは、@ReplaceWithMockアノテーションを使用してコンテキストから Bean を置き換えます。

しかし、残念ながら@Qualifierアノテーションのない依存関係に対してのみ機能します。

つまり、私のテストは次のようになります。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(loader = SpringockitoAnnotatedContextLoader.class, classes = {TestContext.class})
public class ControllerTest {

    @Autowired
    @ReplaceWithMock
    private PasswordService passwordService ;
    @Autowired
    @ReplaceWithMock
    private Validator validator;
    @Autowired
    @ReplaceWithMock
    private ReportService reportService;
    @Autowired
    @ReplaceWithMock
    private DateCalculator dateCalculator;
    @Autowired
    @ReplaceWithMock
    private Accessor accessor;

    @Autowired
    private Controller controller;

}

最後のケースでは、コンテキストを初期化した後、DateCalculator および Accessor Bean のみが必要なモックに正しく置き換えられますが、別の Bean は main context からの通常の Bean として自動配線されます。

デバッグ後、QualifierAnnotationAutowireCandidateResolverが Bean を正しく識別できないことがわかりました。229から始まる以下の行:

RootBeanDefinition bd = (RootBeanDefinition) bdHolder.getBeanDefinition();
AutowireCandidateQualifier qualifier = bd.getQualifier(type.getName());

Spring はモックされた依存関係から修飾子を抽出しようとしましたが、空です。

オブジェクトをモックするために依存関係を @Qualifier に正しく置き換える方法を知っておくとよいでしょう。

4

2 に答える 2

2

編集:ホワイトボックスの代替へのリンクを追加しました。Mockitoの以降のバージョンでは表示されなくなります

別の投稿で提案されているように、mockitos を使用@Mock@InjectMocksて、テストしたいものをクラスに注入することができます。以前は、Spring Managed Bean をテストするのに最適な方法だと思っていましたが、今では問題があると思います。によって行われた注入が@InjectMocks失敗した場合、それは静かに行われ、その理由はわかりません。テストを作成するときは管理可能ですが、このようないくつかのテストがあり、誰かが行ったアプリケーションコンテキストへの意図しない小さな変更のため、またはマイナーな異常を導入したマージの後、いくつかのテストが nullpointers で失敗し始める場合、または同様の場合、必要以上に混乱します。

代わりに、 mockitos を使用することをお勧めしますWhitebox。以下の例を参照してください。これを使用すると、どのフィールドにどのオブジェクトを「注入」するかを明示的に指定でき、複雑な状況では、複数のオブジェクトに注入できます。Mockito は注入時に Whitebox を使用します (ただし、すべての例外を飲み込みます)。

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration( /*something that fits your setup*/ )
public class ControllerTest {
    @Autowired
    private PasswordService passwordService ;
    @Autowired
    private Validator validator;
    @Autowired
    private ReportService reportService;



    @Autowired
    private Controller testObject;

    @Before
    public void setupBefore() {

        //Since this "injection" is done manually the qualifiers does not matter
        Whitebox.setInternalState(testObject, "passwordService", passwordService);
        Whitebox.setInternalState(testObject, "validator", validator);
        Whitebox.setInternalState(testObject, "reportService", reportService);
    }

    @Test
    public void testSomething() {
    }
}

通常の単体テストを行っている場合はWhitebox、Spring コンテキストなしでテストを行うのに役立ちます。私はそのアプローチを強くお勧めします (しかし、それは少し話題から外れています。統合テストを行っていることに気付く前に、私が書いた例を投稿しません ;))。


編集: Mockito の新しいバージョンを使用している場合、Whitebox が消えたことに気付くでしょう。代わりに何をすべきでしょうか? 私はその状況に直面し、アドバイスを求めました:フィールドを設定するために、Mockito 2.2 で Whitebox の代わりに何を使用しますか?

于 2014-11-30T18:41:24.753 に答える