Чи може Mockito заглушити метод, не враховуючи аргументу?


302

Я намагаюся перевірити деякий застарілий код, використовуючи Mockito.

Я хочу заглушити a, FooDaoякий використовується у виробництві наступним чином:

foo = fooDao.getBar(new Bazoo());

Я можу написати:

when(fooDao.getBar(new Bazoo())).thenReturn(myFoo);

Але очевидною проблемою є те, що getBar()ніколи не викликається тим самим Bazooоб'єктом, до якого я заглушив метод. (Прокляття цього newоператора!)

Мені подобається, якби я міг заглушити метод таким чином, що він повертається myFooнезалежно від аргументу. Якщо цього не зробити, я прослухаю інші попередні пропозиції, але дуже хотів би уникати зміни виробничого коду, поки не з’явиться розумне покриття тесту.

Відповіді:


456
when(
  fooDao.getBar(
    any(Bazoo.class)
  )
).thenReturn(myFoo);

або (щоб уникнути nulls):

when(
  fooDao.getBar(
    (Bazoo)notNull()
  )
).thenReturn(myFoo);

Не забудьте імпортувати відповідники (доступно багато інших):

Для Mockito 2.1.0 та новіших версій:

import static org.mockito.ArgumentMatchers.*;

Для старих версій:

import static org.mockito.Matchers.*;

2
Мені подобається, коли відповідь передує закінченню "прийняти відповідь заморозити".
Ерік Вілсон

10
Є такий, notNull(Bazoo.class)як any(Bazoo.class)(можливо, його не було на час цієї відповіді)
Dandre Allison

2
я мав кілька особливе становище , де я міг би мати одне з двох можливих аргументів - Bazooчи Cazooякі є підкласами, скажімо, Azoo. для Bazooмене потрібно було повернутися foo, але для Cazooповернення bar. у цій ситуації запропоноване Matchers.any()рішення не працює, однак Matchers.isA()працює ідеально.
Танвір

3
org.mockito.Matchersтепер застаріло - використовуйте org.mockito.ArgumentMatchersнатомість, тобто import static org.mockito.ArgumentMatchers.*(див. документи )
DontDivideByZero

when(myFoo.knowsWhatsUp()).thenReturn(myMoney);
6рхіда

18

Використовуйте так:

when(
  fooDao.getBar(
    Matchers.<Bazoo>any()
  )
).thenReturn(myFoo);

Перш ніж вам потрібно імпортувати Mockito.Matchers


1
Це знецінено!
DrB

15

http://site.mockito.org/mockito/docs/1.10.19/org/mockito/Matchers.html

anyObject() має відповідати вашим потребам.

Крім того, ви завжди можете розглянути можливість реалізації hashCode()та equals()для Bazooкласу. Це зробить ваш приклад коду таким, яким ви хочете.


Погодився з другою пропозицією, але я все ще не хочу робити цього з нетехнічних причин.
Ерік Вілсон

1
Клас Matchers застарілий (див. Документи - "Цей клас, ймовірно, буде видалено у версії 3.0" )
Йоханнес Рабауер

1

Ще один варіант - покладатися на старий хороший equalsспосіб моди . Поки аргумент в whenмакеті equalsаргументується в тестованому коді, тоді Mockito буде відповідати макеті.

Ось приклад.

public class MyPojo {

    public MyPojo( String someField ) {
        this.someField = someField;
    }

    private String someField;

    @Override
    public boolean equals( Object o ) {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;
        MyPojo myPojo = ( MyPojo ) o;
        return someField.equals( myPojo.someField );
    }

}

то, припускаючи, що ви знаєте, яке значення someFieldбуде, ви можете знущатися над цим так.

when(fooDao.getBar(new MyPojo(expectedSomeField))).thenReturn(myFoo);

плюси: Це більш чітко, ніж відповіді any. Як рецензент коду, я пильную відкритість для anyнаписання коду молодшим розробникам, коли він переглядає логіку їх коду для створення відповідного об'єкта, що передається.

con: Іноді поле, яке передається об'єкту, є випадковим ідентифікатором. У цьому випадку ви не можете легко побудувати очікуваний об’єкт аргументу у вашому макетному коді.

Інший можливий підхід - використовувати Answerоб’єкт Mockito, який можна використовувати разом із whenметодом. Answerдозволяє перехоплювати фактичний виклик та перевіряти вхідний аргумент та повертати макетний об’єкт. У наведеному нижче прикладі я використовую, anyщоб знайти будь-який запит щодо методу, що висміюється. Але тоді в Answerлямбді я можу далі перевірити аргумент Базо ... можливо, щоб переконатися, що йому передано належний ідентифікатор. Я вважаю за краще це над anyсобою, щоб хоча б деяка перевірка була проведена на аргументі.

    Bar mockBar = //generate mock Bar.

    when(fooDao.getBar(any(Bazo.class))
    .thenAnswer(  ( InvocationOnMock invocationOnMock) -> {
        Bazo actualBazo = invocationOnMock.getArgument( 0 );

        //inspect the actualBazo here and thrw exception if it does not meet your testing requirements.
        return mockBar;
    } );

Отже, підсумовуючи все, мені подобається покладатися на equals(де очікуваний аргумент та фактичний аргумент повинні бути рівними один одному), і якщо рівне неможливо (через неможливість передбачити фактичний стан аргументу), я вдаюся щоб Answerоглянути аргумент.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.