簡體   English   中英

Mockito 的 argumentCaptor 示例

[英]Example of Mockito's argumentCaptor

誰能給我提供一個示例,說明如何使用org.mockito.ArgumentCaptor class 以及它與 mockito 提供的簡單匹配器有何不同。

我閱讀了提供的 mockito 文檔,但這些文檔並沒有清楚地說明,沒有一個能夠清楚地解釋它。

我同意@fge 所說的,更多。 讓我們看看例子。 考慮你有一個方法:

class A {
    public void foo(OtherClass other) {
        SomeData data = new SomeData("Some inner data");
        other.doSomething(data);
    }
}

現在如果你想檢查內部數據,你可以使用捕獲器:

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);

兩個主要區別是:

  • 當您捕獲甚至一個參數時,您就能夠對這個參數進行更精細的測試,並使用更明顯的代碼;
  • 一個ArgumentCaptor可以捕捉不止一次

為了說明后者,假設您有:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);

verify(x, times(4)).someMethod(captor.capture()); // for instance

然后捕獲者將能夠讓您訪問所有 4 個參數,然后您可以分別對其執行斷言。

事實上,這個或任何數量的參數,因為VerificationMode不限於固定數量的調用; 無論如何,如果您願意,俘虜者將允許您訪問所有這些文件。

這也有一個好處,即這樣的測試(恕我直言)比必須實現自己的ArgumentMatcher更容易編寫——特別是如果你將 mockito 與 assertj 結合起來。

哦,請考慮使用 TestNG 而不是 JUnit。

進行全面檢查的步驟是:

首先,准備參數捕獲器:

ArgumentCaptor<ArgumentClass> argumentCaptor = ArgumentCaptor.forClass(ArgumentClass.class);

其次,驗證對依賴組件(被測對象的合作者)的調用。

times(1) 是默認值,所以需要添加它。

verify(dependentOnComponent, times(1)).method(argumentCaptor.capture());

第三,使用捕獲者的 getValue() 獲取傳遞給合作者的參數

ArgumentClass someArgument = messageCaptor.getValue();

、使用 someArgument 進行斷言

我創建了這個示例來模擬一個非常簡單的服務,該服務使用存儲庫保存字符串(無依賴注入,無實體),只是為了快速教授 ArgumentCaptor。

  • 該服務接收、轉換為大寫並修剪名稱,然后調用存儲庫。
  • 存儲庫“保存”了字符串。
  • 使用 ArgumentCaptor 我想知道哪個值被傳遞到存儲庫,然后檢查它是否按預期被修剪和大寫

3 個類:PersonService、PersonRepository 和 PersonServiceTest(省略包)

public class PersonService {

    private PersonRepository personRepository;

    public void setPersonRepository(final PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    public void savePerson(final String name) {
        this.personRepository.save(name.toUpperCase().trim());
    }

}

public class PersonRepository {

    public void save(final String person) {
        System.out.println(".. saving person ..");
    }
}


import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

class PersonServiceTest {

    @Test
    void testPersonService() {

        // Create the repository mock
        final PersonRepository personRepositoryMock = mock(PersonRepository.class);

        // Create the service and set the repository mock
        final PersonService personService = new PersonService();
        personService.setPersonRepository(personRepositoryMock);

        // Save a person
        personService.savePerson("Mario ");

        // Prepare an ArgumentCaptor to capture the value passed to repo.saveMethod
        final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

        // Capture the argument passed in the unique method invocation
        verify(personRepositoryMock, times(1)).save(captor.capture());

        // Check if the captured value is the expected one
        final String capturedParameter = captor.getValue();
        assertEquals("MARIO", capturedParameter);
    }
}

您可能希望將 verify() 與 ArgumentCaptor 結合使用以確保在測試中執行,並使用 ArgumentCaptor 來評估 arguments:

ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());
    

參數的值顯然可以通過 argument.getValue() 訪問,以進行進一步的操作/檢查或任何您想做的事情。

對此和大多數事情使用注釋@Spy、@Mock、@Captor 等。

這是一個示例(使用 JUnit 5):

public class Blam
{
  public void foo(final OtherClass other)
  {
    final SomeData data = new SomeData("Some inner data");
    other.doSomething(data);
  }
}

@ExtendWith(MockitoExtension.class)
public class TestBlam
{
  @Captor
  private ArgumentCaptor<SomeData> captorSomeData;

  private Blam classToTest;

  @Mock
  private OtherClass mockOtherClass;

  @BeforeEach
  void beforeEach()
  {
    classToTest = new Blam();
  }

  @Test
  void foo_allGood_success()
  {
    SomeData actualSomeData;

    classToTest.foo(mockOtherClass);
    
    verify(mockOtherClass).doSomething(captorSomeData.capture());
    
    actualSomeData = captorSomeData.getValue();
    
    assert(stuff about actualSomeData);
  }
}

在這里,我給你一個回調方法的正確例子。 所以假設我們有一個類似方法 login() 的方法:

 public void login() {
    loginService = new LoginService();
    loginService.login(loginProvider, new LoginListener() {
        @Override
        public void onLoginSuccess() {
            loginService.getresult(true);
        }

        @Override
        public void onLoginFaliure() {
            loginService.getresult(false);

        }
    });
    System.out.print("@@##### get called");
}

為了讓例子更清晰,我也把所有的幫助類放在這里: loginService 類

public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){

    String username  = loginProvider.getUsername();
    String pwd  = loginProvider.getPassword();
    if(username != null && pwd != null){
        callback.onLoginSuccess();
    }else{
        callback.onLoginFaliure();
    }

}

@Override
public void getresult(boolean value) {
    System.out.print("login success"+value);
}}

我們有監聽器 LoginListener 為:

interface LoginListener {
void onLoginSuccess();

void onLoginFaliure();

}

現在我只想測試類 Login 的方法 login()

 @Test
public void loginTest() throws Exception {
    LoginService service = mock(LoginService.class);
    LoginProvider provider = mock(LoginProvider.class);
    whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
    whenNew(LoginService.class).withNoArguments().thenReturn(service);
    when(provider.getPassword()).thenReturn("pwd");
    when(provider.getUsername()).thenReturn("username");
    login.getLoginDetail("username","password");

    verify(provider).setPassword("password");
    verify(provider).setUsername("username");

    verify(service).login(eq(provider),captor.capture());

    LoginListener listener = captor.getValue();

    listener.onLoginSuccess();

    verify(service).getresult(true);

也不要忘記在測試類上方添加注釋

@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)

暫無
暫無

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

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