我有:
SomeClass a = spy(SomeClass.class)
SomeClass
有private int myValue
。
我想将myVlaue
设置为3。
我怎么能用Mockito做到这一点?
(如果不能与Mockito合作,那么我的下一个最佳选择是什么,最好不要丢弃使用Mockito的代码)。
注意:
getMyValue()
,我已经知道我可以做到。setMyValue(int newMyValue)
,我不想要它。答案 0 :(得分:2)
到目前为止,我提出的最佳选择是反思:
Field myVarField = SomeClass.class.getDeclaredField("myVarField");
myVarField.setAccessible(true);
myVarField.set(someClass,3);
答案 1 :(得分:1)
反思是正确的答案。除了@InjectMocks
或the recently removed internal class Whitebox之外,Mockito根本不关心字段,因此您需要自己处理字段访问或在您的间谍上调用setter。
至于理由,我还没有见过,但要记住Mockito的作用:它提供工具和简洁的语法来记录和验证交互方法调用,更具体地说 - 通过内部创建动态子类(代理) )覆盖所有方法。对于字段,没有任何内容可以记录或验证,因为JVM只设置了值;使用字段将有点超出Mockito的范围,并介绍了许多关于哪些字段可以更改的警告(私有?静态?最终?)以及您可以用它们做什么(不是存根或验证多个交互)
虽然Mockito并没有明确建议使用getter,但它们是您可以覆盖/跟踪状态访问的少数几个接口之一,所以有一些东西可以说是在整个Java中使用它们进行封装&# 39;那个缘故。如果你不能设置和读取这样的值:
mockitoMockWithFields.fieldA = 42;
return mockitoMockWithFields.fieldB;
然后你要找Mockito做的就是打败封装或终结;即使对于方法来说,Mockito也不能本地化,所以你自己或者使用不同的库来打败他们可能是非常合理的。
答案 2 :(得分:0)
您的测试中a
到底是什么?
1)如果a
是依赖项:
您不应该在其上强制使用内部状态,而应将模拟配置为在某个调用中返回所需的值,例如Mockito.doReturn("my current value is: 3").when(a).getText()
。
其背后的基本思想是,单元测试应独立于其他单元的实现(因此也应独立于那些实现中的缺陷)。操作依赖项的内部状态会导致您的测试与另一个单元紧密耦合。结果将是一个复杂且难以测试的场景。
2)如果a
是您的受测试的系统:
您可以提供注入myValue
的选项,例如包私有方法setMyValue(final int value)
。一个经典的示例是将时间戳提供程序插入被测系统(例如Supplier<LocalDateTime>
)中,以注入用于测试的修复时间戳(测试无法知道某个操作使用了哪个时间戳,因此它需要为定义明确的测试方案注入修复时间戳记)。这种用于单元测试的实用方法应该是私有的。
旁注: 单元测试必须简单,易于阅读和理解。不要称呼模拟“ a”,请使用适合其性质的名称!在所有测试中,我也经常将被测系统称为“ sut”。因此,很容易区分正在测试的内容和依赖项。
答案 3 :(得分:-1)
尝试以下代码,
use org.springframework.test.util.ReflectionTestUtils
ReflectionTestUtils.setField(yourClass, "yourFieldName", yourFieldValue);