私はそれに注入Beanを持つMicronautクラスをテストしています。私のテストでは、私は提供し@MockBean
、それをオーバーライドするクラスを。しかし、Micronautはまだ本当の依存性を注入しそうです。
@MicronautTest
public class ClassUnderTestTest {
@Inject ClassUnderTest classUnderTest;
@Test
public void test() {
}
@MockBean
Dependency dependency() {
return mock(Dependency.class);
}
}
:私はGithubの最小REPROアップロードhttps://github.com/crummy/micronaut-test-dependenciesを。本当の依存性は、例外をスローし、テストも行います。私は、これが原因で、私の起こることを期待しなかったであろう@MockBean
。
私がする注釈を変更した場合@MockBean(Dependency.class)
、私はこのエラーを取得します:Message: No bean of type [di.failure.example.Dependency] exists
。これは私にはさらに混乱ようだ-今、それは私の本当のか、私のモックの依存関係が解決されませんか?
モックBeanを注入@MockBean
中に、あなたの依存関係があれば、注釈の作品ClassUnderTest
インターフェースによって表されます。発言はしてみましょうDependency
のようなシンプルなインターフェイスです。
package di.failure.example;
public interface Dependency {
void run();
}
あなたのアプリと呼ばれるこのインタフェースの実装を提供することができますDependencyImpl
。
package di.failure.example;
import javax.inject.Singleton;
@Singleton
public class DependencyImpl implements Dependency {
@Override
public void run() {
throw new RuntimeException("I don't want this to load!");
}
}
さて、テスト目的のために、あなたは置き換え、そのモックを定義することができますDependencyImpl
:
package di.failure.example;
import io.micronaut.test.annotation.MicronautTest;
import io.micronaut.test.annotation.MockBean;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import static org.mockito.Mockito.mock;
@MicronautTest
public class ClassUnderTestTest {
@Inject
ClassUnderTest classUnderTest;
@Test
public void test() {
classUnderTest.run();
}
@MockBean(DependencyImpl.class)
public Dependency dependency() {
return mock(Dependency.class);
}
}
このテストを実行してから返されたモックdependency()
メソッドの代わりに使用されていますDependencyImpl
。
使用して@Replaces
注釈を
セルジオは、コメント欄で述べたあなたが使用してクラスベースのBeanの依存関係を置き換えることができ@Replaces
、注釈を。次の例を考えてみます。
package di.failure.example;
import io.micronaut.context.annotation.Replaces;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;
import javax.inject.Inject;
import javax.inject.Singleton;
@MicronautTest
public class ClassUnderTestTest {
@Inject
ClassUnderTest classUnderTest;
@Test
public void test() {
classUnderTest.run();
}
@Replaces(Dependency.class)
@Singleton
public static class MockDependency extends Dependency {
public MockDependency() {
System.out.println("MockDependency.<init>");
}
@Override
void run() {
System.out.println("Does not throw any exception...");
}
}
}
この例では、クラスを定義しているMockDependency
と我々は交換するMicronautのDIメカニズム指示Dependency
で豆をMockDependency
。しかし、私たちが覚えておく必要がある1つ重要なことがある-私たちはので、MockDependency
拡張Dependency
クラスを、親構築物が呼び出されます。ので、あなたが疑問に示した例では、このケースでは動作しませんDependency.<init>
投げRuntimeException
、テストが失敗しました。この変形例では私はこの1つのように使用するクラスを持っています:
package di.failure.example;
import javax.inject.Singleton;
@Singleton
public class Dependency {
public Dependency() {
System.out.println("Dependency.<init>");
}
void run() {
throw new RuntimeException("I don't want this to load!");
}
}
私は、テストを実行すると、それは通過して、私は次のコンソール出力を参照してください。
Dependency.<init>
MockDependency.<init>
Does not throw any exception...
比較主な違いは、@MockBean
の場合であることである@Replaces
あなたの具象クラスのオブジェクトを使用しています。回避策として(私たちは本当にMockitoモックオブジェクトが必要な場合)、内部でモックを作成し、このオブジェクトへの呼び出しを委任し、このようなものです:
@Replaces(Dependency.class)
@Singleton
public class MockDependency extends Dependency {
private final Dependency delegate;
public MockDependency() {
this.delegate = mock(Dependency.class);
}
@Override
void run() {
delegate.run();
}
}