gpt4 book ai didi

java - 覆盖 Micronaut 测试中的依赖项

转载 作者:搜寻专家 更新时间:2023-10-31 19:36:37 27 4
gpt4 key购买 nike

我正在测试一个 Micronaut 类,其中注入(inject)了一个 bean。在我的测试中,我提供了一个 @MockBean 类来覆盖它。然而,似乎 Micronaut 仍然注入(inject)了真正的依赖。

@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) 那么我会收到此错误:消息:[di.failure.example.Dependency] 类型的 bean 不存在。这似乎让我更加困惑 - 现在它没有解决我的真实或模拟依赖?

最佳答案

@MockBean 注入(inject)模拟 bean|如果您的依赖项在 ClassUnderTest 中,则注释有效由接口(interface)表示。比方说 Dependency是一个简单的界面,例如:

package di.failure.example;

public interface Dependency {
void run();
}

您的应用程序可能会为此接口(interface)提供一个实现,称为 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注释

作为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...");
}
}
}

在这个例子中我们定义了一个类 MockDependency我们指示 Micronaut 的 DI 机制替换 Dependency bean 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!");
}
}

当我运行测试时,它通过了并且我看到了以下控制台输出:

Dependency.<init>
MockDependency.<init>
Does not throw any exception...

@MockBean 相比的主要区别是在@Replaces的情况下吗?您正在使用具体的类对象。作为解决方法(如果我们真的需要 Mockito 模拟对象)是在内部创建一个模拟并委托(delegate)对该对象的调用,如下所示:

@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();
}
}

关于java - 覆盖 Micronaut 测试中的依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53132087/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com