簡體   English   中英

Mockito 沒有從具有多個“何時”條件的模擬方法返回正確結果

[英]Mockito not returning correct result from mocked method with multiple “when” conditions

我有一個簡單的 DTO class:

@Data // lombok
public class MyObj {
    private int id;
    private String someProperty;
}

和一個 class 以及 DTO object 的一些計算邏輯:

public class MyClass {
    public String doSomething(MyObj obj) {
        // some calculations
    }
}

我試圖模擬MyClass以在一些單元測試中使用它,但遇到了一個奇怪的問題。 因此,我創建了這個最小的測試代碼來說明這個問題:

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

出於某種原因, myClass.doSomething(myObjFirst)產生字符串"SECOND"而不是預期的"FIRST" ,因此測試在第一次斷言時失敗。

我究竟做錯了什么?

解決方案

存根時,將預期對象包裝到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 似乎使用equals方法來檢測模擬方法的給定參數(需要參考文檔)。

由於Lombok 的@Data注釋,生成了一個MyObj.equals實現,它通過字段idsomeProperty比較對象。 因為myObjFirstmyObjSecond上的兩個字段都是null ,並且因為最后一個存根具有最高的重要性,所以 Lombok 首先將提供給myClass.doSomething的參數與myObjSecond進行比較,立即找到匹配項並返回"SECOND"

如果MyObj中省略了 Lombok 的@Data注釋,則上述代碼將按原樣工作,因為MyObj.equals方法將默認為 object 參考比較,從而使myObjFirst不等於myObjSecond

但是,在這種情況下, myObjFirst等於myObjSecond等於new MyObj() ,除非它們的屬性設置為不同的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM