19

BaseITCaseという基本クラスを拡張する Spring Framework でいくつかの統合テストを実行しています。
このような:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {AppCacheConfiguration.class, TestConfiguration.class}, loader = SpringBootContextLoader.class)
@Transactional
@WebMvcTest
public abstract class BaseITCase{...}
...
public class UserControllerTest extends BaseITCase {...}

問題は、テストの 1 つに複数の宣言があることです: @MockBean が内部にあり、このテストが実行された瞬間、Spring はコンテキストを再作成し、これに続くテストは間違った Bean を使用することがあります (@ を使用してテスト用に正確に作成されたコンテキストから)モックビーン)。Bean のハッシュコードが異なることを確認しただけで、そのことがわかりました。

@EventListener を使用すると、非常に重要になります。間違ったコンテキスト (既に実行が終了したテスト クラスのコンテキスト) のリスナーが呼び出され、そこに間違った Bean があるためです。

そのための回避策はありますか?

すべての @MockBean 宣言を基本クラスに移動しようとしましたが、新しいコンテキストが作成されないため、正常に機能しました。ただし、基本クラスが重くなりすぎます。また、このテスト用にダーティ コンテキストを作成しようとしましたが、次のテストでは、コンテキストが既に閉じられているというメッセージが表示されて失敗します。

4

2 に答える 2

21

その理由は、@MockBean を持つテストのスプリング構成が残りのテストと異なるため、スプリング フレームワークは以前に使用されたコンテキストをキャッシュできず、再度ロードする必要があるためです。ここで、より詳細な説明を見つけることができます: https://github.com/spring-projects/spring-boot/issues/10015

あなたが言ったように、モック Bean を親クラスに移動すると、コンテキストはリロードされません。これは、Bean 構成が同じままであるため理にかなっています。

考えられる回避策は、モック Bean を単純なモックとして定義し、必要な場所に手動で注入することです。

たとえば、次UserControllerの依存関係がありFooます。

public class UserControllerTest extends BaseITCase {

    private Foo foo = Mockito.mock(Foo.class);

    @Autowired
    private UserController userController;

    @Before
    public void setUp() {
        super.setup();

        this.userController.setFoo(foo);
    }
}

@Component
public class UserController {

    private Foo foo;

    @Autowired
    public void setFoo(final Foo foo) {
        this.foo = foo;
    }
}

お役に立てれば。

于 2018-02-26T11:57:14.683 に答える