it-swarm.com.ru

Пример Mockito argumentsCaptor

Может ли кто-нибудь предоставить мне пример, показывающий, как используется класс org.mockito.ArgumentCaptor и чем он отличается от простые сопоставители, которые предоставляются с mockito.

Я прочитал предоставленные документы, но они не иллюстрируют это ясно, и при этом они не в состоянии объяснить это с ясностью.

90
Ujjwal

Я согласен с тем, что сказал @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);
125
Slava Shpitalny

Два основных различия:

  • когда вы фиксируете хотя бы один аргумент, вы можете сделать более сложные тесты для этого аргумента и с более очевидным кодом;
  • ArgumentCaptor может захватывать больше, чем один раз.

Чтобы проиллюстрировать последнее, скажем, у вас есть:

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

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

Тогда похититель сможет дать вам доступ ко всем 4 аргументам, которые вы затем сможете выполнять по отдельности.

Фактически это или любое количество аргументов, поскольку VerificationMode не ограничено фиксированным числом вызовов; в любом случае захватчик предоставит вам доступ ко всем из них, если вы пожелаете.

Это также имеет то преимущество, что такие тесты (imho) гораздо проще написать, чем реализовать собственные ArgumentMatchers - особенно если вы комбинируете mockito с assertj.

О, и, пожалуйста, рассмотрите возможность использования TestNG вместо JUnit.

27
fge

Шаги для полной проверки:

Подготовьте похитителя:

ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);

убедитесь, что вызов (1) зависит от компонента (соавтора испытуемого) и является значением по умолчанию, поэтому его не нужно добавлять.

verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());

Получить аргумент, переданный сотруднику

SomeArgumentClass someArgument = messageCaptor.getValue();

someArgument может использоваться для утверждений

3
Lho Ben

Здесь я приведу вам пример одного метода обратного вызова. поэтому предположим, что у нас есть метод, подобный методу 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)
0
Vikram singh