java - 尽管创建了 2 个不同的模拟,但 InjectMocks 错误地将相同的模拟注入到 2 个相似类型的不同字段中
问题描述
我有一个类有 2 个类似类型的字段。我嘲笑过他们俩。但是当我使用 InjectMocks 时,注入模拟错误地将单个模拟注入到这两个字段中。
这是示例代码类:
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import java.util.Set;
import java.util.function.Consumer;
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class TestClass {
private final Consumer<Set<Integer>> intConsumer;
private final Consumer<Set<String>> stringConsumer;
void PrintClass(){
System.out.println("intConsumers: " + intConsumer);
System.out.println("stringConsumers: " + stringConsumer);
}
}
这是测试类:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.Set;
import java.util.function.Consumer;
@RunWith(MockitoJUnitRunner.class)
public class TestClassTest {
@Mock private Consumer<Set<Integer>> intConsumer;
@Mock private Consumer<Set<String>> stringConsumer;
@InjectMocks private TestClass testClass;
@Test
public void testPrint(){
testClass.PrintClass();
}
}
这是我运行测试时的输出:testPrint() - intConsumer 被注入到 intConsumer 和 stringConsumer 中。
intConsumers: intConsumer
stringConsumers: intConsumer
Process finished with exit code 0
我正在使用 Maven。
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.7.19</version>
</dependency>
我创建了这个私有构造函数,专门用于使用 InjectMocks 进行测试。我不想让它公开/包私有,所以我不能使用字段注入。我也不想使用公共设置器公开这些字段。另外,我不想让我的领域成为非最终领域。
我已经尝试将 mockito-version 升级到 3.5.10,但它仍然有这个错误。我也尝试过让我的字段最终化并使用 setter - 然后 Injection 工作正常 - 但我不想暴露我的 setter。我也尝试过使用构造函数注入来命名模拟 @Mock(name = "mock") ,但效果不佳。
我在这里错过了什么吗?有没有办法让它与私有构造函数注入一起工作?
解决方案
这是 Mockito 中的一个开放错误。
据我所知,PropertyAndSetterInjection 考虑了泛型类型和@Mock 的名称属性,因此它可以按预期进行字段注入。但它不适用于构造函数,因为 ConstructorInjection 仅使用 SimpleArgumentResolver 这很好......非常简单,并且没有像属性注入器那样的任何 MockCandidateFilter 。
通常,您会:
- 删除 @InjectMocks 并在测试的 setup 方法中构造 TestClass 实例。恕我直言,这是一种侵入性较小的方法。
- 或者,如上所述,field 和 setter 注入工作。
这两种方法都不适用于您的约束(私有构造函数、无设置器、最终字段)。
在这种情况下,您可以借助反射来构建实例:
@Before
public void setUp() throws IllegalAccessException,
InvocationTargetException,
InstantiationException,
NoSuchMethodException {
final Constructor<TestClass> constructor = TestClass.class.getDeclaredConstructor(Consumer.class, Consumer.class);
constructor.setAccessible(true);
testClass = constructor.newInstance(intConsumer, stringConsumer);
}
推荐阅读
- php - 尝试获取附件 url 后未定义的 url
- python - 追加到字典与数据帧之间的时间复杂度
- python-3.x - 如何将任何数字转换为 numpy nan
- sql - 使用 Where Not Exists 更新语句
- javascript - 检查 html 输入元素值的 if 语句
- laravel - 如何使用我的服务器 SMTP 详细信息在 Laravel 中发送电子邮件?
- swift - 快照视图不包含 iOS 10 上的图像
- c# - 在 ItemInserting 上未发生 ListView 验证
- java - 想在java中打印特定单元格的所有行值
- java - 如何阻止 Recyclerview 产生重复项并停止洗牌?