簡體   English   中英

測試是否調用了另一種方法

[英]Test if another method was called

所以我確定那里有類似的東西,但我一直在尋找一個小時,並沒有找到我正在尋找的東西。 說我有一個看起來像這樣的課:

public class MyClass
{
    public void myMethod(boolean shouldCallOtherMethod)
    {
        if(shouldCallOtherMethod)
        {
            otherMethod();
        }
    }

    public void otherMethod()
    {
        System.out.println("Called");
    }
}

我如何制作這樣的作品呢?

@Test
public void shouldCallMethod()
{
    MyClass myClass = new MyClass();
    myClass.myMethod(true)

    // verify myClass.otherMethod method was called
}

使用Mockito ,你可以像這樣對真實物體進行間諜活動

import org.junit.Test;
import static org.mockito.Mockito.*;
public class MyClassTest {
    @Test
    public void otherMethodShouldBeCalled() {
        MyClass myClass = new MyClass();
        MyClass spy = spy(myClass);

        spy.myMethod(true);
        verify(spy).otherMethod();
    }
}

有一些問題,所以看一下相關的文檔

假設MokeysClass有一個像這樣聲明的構造函數,其中Foo是其他類。

public MokeysClass(String name, int counter, Foo myFoo)

我會像這樣寫我的測試。

@RunWith(MockitoJUnitRunner.class)
public class TestArray {
    @Mock 
    private Foo mockMyFoo;
    private String nameToInject = "Mokey";
    private int counterToInject = 42;

    @Spy 
    private MokeysClass toTest = new MokeysClass(nameToInject, counterToInject, mockMyFoo);

    @Test
    public void shouldCallMethod() {
        toTest.myMethod(true);
        verify(toTest).otherMethod();
    }
}

所以我明確說明在創建測試對象時要調用哪個構造函數,以及傳遞給它的參數。

有一些原因不依賴@InjectMocks為我執行此步驟,特別是如果被測試的類更復雜並且具有多個構造函數。 Mockito選擇具有最多參數的構造函數,但如果有多個構造函數具有相同數量的參數,Mockito可以選擇任何構造函數; 也就是說,行為是未定義的。

一旦Mockito選擇了構造函數,它就會檢查該構造函數是否實際上可以用於構造函數注入。 如果,將不使用構造函數注入

  • 所選構造函數的一個或多個參數是基本類型,
  • 所選構造函數的一個或多個參數的類型是最終類,
  • 所選構造函數的一個或多個參數的類型是私有類,
  • 該類的唯一構造函數是默認構造函數。

如果這些條件中的任何一個成立,對於Mockito選擇的構造函數,則不會使用構造函數注入。 在這種情況下,類必須具有默認構造函數,否則Mockito將拋出異常。

選擇是否應用構造函數注入時Mockito使用的標准的復雜性意味着添加或刪除構造函數,或更改構造函數的參數,可以使Mockito從使用構造函數注入切換到使用setter和field注入; 或者使用setter和field injection來使用構造函數注入。 即使更改的構造函數不是將用於構造函數注入的構造函數,也會發生這種情況。

因此,任何使用構造函數注入的測試都會自動變得非常脆弱; 從某種意義上說,與測試本身沒有直接關系的變化會導致測試失敗。 這樣的故障可能很難排除故障。

@InjectMocks注釋旨在用於執行依賴注入的Spring等框架; 對於使用Spring的類的測試,它可能是非常寶貴的。 但是如果依賴注入不屬於你的類,我強烈建議避免使用@InjectMocks它的脆弱性。 您確實希望您的測試代碼像生產代碼一樣易於維護和排除故障。

不推薦 ,但你可以窺探真實的對象:)

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.BDDMockito.verify;

@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {

    @Spy
    private MyClass sut; // System Under Test

    @Test
    public void shouldCallMethod() {

        // when
        sut.myMethod(true);

        // then
        verify(sut).otherMethod();
    }
}

結果:

Tests Passed: 1 passed in 0,203 s

更改代碼后: sut.myMethod(false);

Wanted but not invoked:
sut.otherMethod();
-> at my.custom.MyClassTest.shouldCallMethod(MyClassTest.java:23)

來源: 對真實物體進行間諜活動


帶構造函數注入的魔術版

@Mock
private LexAnalyzer lexAnalyzer;

@Spy
@InjectMocks
private SyntaxAnalyzer sut; // System Under Test

@Test
public void shouldCallMethod() {

    // when
    sut.myMethod(true);

    // then
    verify(sut).otherMethod();
}

SyntaxAnalyzer.java

public class SyntaxAnalyzer {

    private final LexAnalyzer lexAnalyzer;

    public SyntaxAnalyzer(LexAnalyzer lexAnalyzer) {
        this.lexAnalyzer = lexAnalyzer;
    }
...

經過測試,有效;)

我想你想看看Mock對象。 您可以創建MyClass的模擬,然后設置在調用myMethod時調用otherMethod()的期望,如果未調用則調整失敗。

以下是對java的非常好的概述 - http://www.scalatest.org/user_guide/testing_with_mock_objects

使用Mocks的另一個主要好處是,您可以避免在測試中產生副作用,例如記錄到NSLog或訪問Web服務器或打印。

暫無
暫無

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

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