簡體   English   中英

具有內部方法參考的Mockito Spying on Class

[英]Mockito Spying on Class that has an internal method reference

在使用@Spy注釋監視服務並讓Mockito創建顯式調用構造函數的Server詩句時,我發現行為有所不同。

public class MyService {
    private final Supplier<String> methodBCall;

    public MyService() {
        methodBCall = this::methodB;
    }

    public void methodA() {
        methodBCall.get();
    }

    public String methodB() {
        return "methodB";
    }
}
@RunWith(MockitoJUnitRunner.class)
public class MyTest {

    @Spy
    private MyService myService1;
    @Spy
    private MyService myService2 = new MyService();

    @Test
    public void testSucceeds() {
        myService1.methodA();
        verify(myService1, times(1)).methodA();
        verify(myService1, times(1)).methodB();
    }

    @Test
    public void testFails() {
        myService2.methodA();
        verify(myService2, times(1)).methodA();
        verify(myService2, times(1)).methodB();
    }
}

測試失敗的原因是

Wanted but not invoked:
myService2.methodB();
-> at com.phemi.services.policy.impl.MyTest.testFails

為什么這兩個行為不同? Mockito在初始化myService1使其能夠監視methodB時在做什么?

這是一個簡化的示例,在本例中,為了正確測試我的服務,我需要使用參數調用其構造函數(因此不能將@Spy與默認構造函數一起使用)。 但是,當我這樣做時,我無法正確驗證方法調用。

spymyService2對象已經被構造之后,所以具有在一個方法調用時才創建constructor並不有益的,因為它包含的方法參照初始對象(其不是spy對象)。

當您比較兩種情況的實現時,差異變得更加明顯:

Mockito.spy(Class)

public static <T> T spy(Class<T> classToSpy) {
    return MOCKITO_CORE.mock(classToSpy, withSettings()
            .useConstructor()
            .defaultAnswer(CALLS_REAL_METHODS));
}

Mockito.spy(Object)

public static <T> T spy(T object) {
    return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
            .spiedInstance(object)
            .defaultAnswer(CALLS_REAL_METHODS));
}

如您所見,第一種情況基於一個類(如果未創建@Spy實例,則使用@Spy ),首先創建一個模擬並在模擬對象上使用構造函數。

在第二種情況下,不考慮構造函數,而是創建了一個不同的實例。

暫無
暫無

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

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