[英]Mockito not returning correct result from mocked method with multiple “when” conditions
I have a simple DTO class:我有一个简单的 DTO class:
@Data // lombok
public class MyObj {
private int id;
private String someProperty;
}
and a class with some computation logic for the DTO object:和一个 class 以及 DTO object 的一些计算逻辑:
public class MyClass {
public String doSomething(MyObj obj) {
// some calculations
}
}
I tried to mock MyClass
to use it in some unit tests, but encountered a weird problem.我试图模拟
MyClass
以在一些单元测试中使用它,但遇到了一个奇怪的问题。 Therefore, I created this minimal test code to illustrate the issue:因此,我创建了这个最小的测试代码来说明这个问题:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
private final MyObj myObjFirst = new MyObj();
private final MyObj myObjSecond = new MyObj();
@Mock
private MyClass myClass;
@Before
public void setUp() {
doReturn("OTHER")
.when(myClass)
.doSomething(any(MyObj.class));
doReturn("FIRST")
.when(myClass)
.doSomething(myObjFirst);
doReturn("SECOND")
.when(myClass)
.doSomething(myObjSecond);
}
@Test
public void doSomething() {
assertEquals("FIRST", myClass.doSomething(myObjFirst)); // fail, actual value "SECOND"
assertEquals("SECOND", myClass.doSomething(myObjSecond));
assertEquals("OTHER", myClass.doSomething(new MyObj()));
assertEquals("OTHER", myClass.doSomething(new MyObj()));
}
}
For some reason, myClass.doSomething(myObjFirst)
produces the string "SECOND"
instead of the expected "FIRST"
, therefore the test fails at the first assert.出于某种原因,
myClass.doSomething(myObjFirst)
产生字符串"SECOND"
而不是预期的"FIRST"
,因此测试在第一次断言时失败。
What am I doing wrong?我究竟做错了什么?
When stubbing, wrap the expected objects into Mockito.same
to match them by reference ( see this answer for different matchers):存根时,将预期对象包装到
Mockito.same
以通过引用匹配它们(请参阅此答案以了解不同的匹配器):
@Before
public void setUp() {
doReturn("OTHER")
.when(myClass)
.doSomething(any(MyObj.class));
doReturn("FIRST")
.when(myClass)
.doSomething(same(myObjFirst)); // <-- HERE
doReturn("SECOND")
.when(myClass)
.doSomething(same(myObjSecond)); // <-- AND HERE
}
Mockito seems to use the equals
method to detect the given argument to the mocked method (reference to docs needed). Mockito 似乎使用
equals
方法来检测模拟方法的给定参数(需要参考文档)。
Due to Lombok's @Data
annotation , a MyObj.equals
implementation is generated, which compares the objects by their fields id
and someProperty
.由于Lombok 的
@Data
注释,生成了一个MyObj.equals
实现,它通过字段id
和someProperty
比较对象。 Because both fields are null
on myObjFirst
and myObjSecond
, and because last stubbing has the highest importance , Lombok first compares the argument given to myClass.doSomething
against myObjSecond
, immediately finding a match and returning "SECOND"
.因为
myObjFirst
和myObjSecond
上的两个字段都是null
,并且因为最后一个存根具有最高的重要性,所以 Lombok 首先将提供给myClass.doSomething
的参数与myObjSecond
进行比较,立即找到匹配项并返回"SECOND"
。
If Lombok's @Data
annotation was omitted from MyObj
, the above code would work as-is, because then MyObj.equals
method would default to object reference comparison, making myObjFirst
not equal to myObjSecond
.如果
MyObj
中省略了 Lombok 的@Data
注释,则上述代码将按原样工作,因为MyObj.equals
方法将默认为 object 参考比较,从而使myObjFirst
不等于myObjSecond
。
In this case, however, myObjFirst
equals myObjSecond
equals new MyObj()
, unless their properties are set to different values.但是,在这种情况下,
myObjFirst
等于myObjSecond
等于new MyObj()
,除非它们的属性设置为不同的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.