Cru*_*mmy 5 java dependency-injection micronaut
我正在测试一个注入了bean的Micronaut类.在我的测试中,我提供了一个@MockBean类来覆盖它.然而,似乎Micronaut仍然注入了真正的依赖.
@MicronautTest
public class ClassUnderTestTest {
@Inject ClassUnderTest classUnderTest;
@Test
public void test() {
}
@MockBean
Dependency dependency() {
return mock(Dependency.class);
}
}
Run Code Online (Sandbox Code Playgroud)
我上传了一个最小的repro到Github:https://github.com/crummy/micronaut-test-dependencies.真正的依赖项会引发异常,测试也会发生异常.我不会因为我的原因而预料到会发生这种情况@MockBean.
如果我更改注释,@MockBean(Dependency.class)那么我会收到此错误:Message: No bean of type [di.failure.example.Dependency] exists.这似乎让我更加困惑 - 现在它无法解决我的真实或我的模拟依赖?
@MockBean如果您的依赖项ClassUnderTest由interface表示,则使用注释注入mock bean .让我们说Dependency是一个简单的界面,如:
package di.failure.example;
public interface Dependency {
void run();
}
Run Code Online (Sandbox Code Playgroud)
您的应用程序可能会为此接口提供一个名为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!");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,出于测试目的,您可以定义替换的模拟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);
}
}
Run Code Online (Sandbox Code Playgroud)
执行此测试并dependency()使用方法返回的模拟代替DependencyImpl.
@Replaces注释正如Sergio在评论部分中提到的,您可以使用@Replaces注释替换基于类的bean依赖项.考虑以下示例:
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...");
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我们定义了一个类,MockDependency并指示Micronaut的DI机制替换Dependencybean MockDependency.但是,我们需要记住一件重要的事情 - 因为我们的MockDependency扩展Dependency类,父构造被调用.您在问题中显示的示例在这种情况下不起作用,因为Dependency.<init>抛出RuntimeException和测试失败.在这个修改过的例子中,我使用了类似这样的类:
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!");
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行测试时它会通过,我会看到以下控制台输出:
Dependency.<init>
MockDependency.<init>
Does not throw any exception...
Run Code Online (Sandbox Code Playgroud)
与之相比的主要区别@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();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1932 次 |
| 最近记录: |