2009-07-17 3 views
181

У меня есть вызов метода, который я хочу высмеять с помощью mockito. Для начала я создал и ввел экземпляр объекта, на который будет вызываться метод. Моя цель - проверить один из объектов в вызове метода.Проверить значение атрибута объекта с помощью mockito

Есть ли способ, которым mockito позволяет утверждать или проверять объект и его атрибуты при вызове метода макета?

пример

Mockito.verify(mockedObject) 
     .someMethodOnMockedObject(
       Mockito.<SomeObjectAsArgument>anyObject()) 

Вместо того чтобы делать anyObject() я хочу, чтобы проверить, что объект аргумент содержит некоторые специфические поля

Mockito.verify(mockedObject) 
     .someMethodOnMockedObject(
       Mockito.<SomeObjectAsArgument>**compareWithThisObject()**) 

ответ

8

http://sites.google.com/a/pintailconsultingllc.com/java/argument-matching-with-mockito

Эта ссылка обеспечивает рабочий пример. Я смог решить ее с помощью той же стратегии.

+1

В ссылке есть следующая строка 'проверить (MessageSender) Пошлите ((Список ) argThat (новый MessagesArgumentMatcher ())); 'который не компилируется. –

+0

@RoeeGavirel вам нужно "import static org.mockito.Matchers.argThat;" –

383

Новая функция добавлена ​​в Mockito делает это еще проще,

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class); 
verify(mock).doSomething(argument.capture()); 
assertEquals("John", argument.getValue().getName()); 

Взгляните на Mockito documentation

+0

, если ваш метод имеет более одного аргумента, вы также должны использовать аргументы «Матчи» для всех остальных. https://akcasoy.wordpress.com/tag/argumentcaptor/ – robsonrosa

+1

Что делать, если есть несколько аргументов? Как вы указываете то, что вас интересует? –

+2

@IgorGanapolsky Предполагая второй параметр String для doSomething, что вам нужно сделать: проверить (mock) .doSomething (argument.capture(), anyString()); – GreenTurtle

39

Еще одна возможность, если вы не хотите использовать ArgumentCaptor (например, потому что вы 'также также используя stubbing), заключается в использовании Hamcrest Matchers в сочетании с Mockito.

import org.mockito.Mockito 
import org.hamcrest.Matchers 
... 

Mockito.verify(mockedObject).someMethodOnMockedObject(Mockito.argThat(
    Matchers.<SomeObjectAsArgument>hasProperty("propertyName", desiredValue))); 
+0

Sidenote: убедитесь, что пакет 'Matchers' верен, поскольку запись той же строки кода с классом' org.mockito.Matchers' вызывает ошибочное исключение, указывающее, что параметр макетной функции просто не соответствует. – buer

34

Я думаю, что самый простой способ для проверки объекта аргумента заключается в использовании refEq метода:

Mockito.verify(mockedObject).someMethodOnMockedObject(Matchers.refEq(objectToCompareWith)); 

Он может быть использован, даже если объект не реализует equals(), потому что отражение используется. Если вы не хотите сравнивать некоторые поля, просто добавьте их имена в качестве аргументов для refEq.

+0

Этот тест для ссылочного равенства (тот же объект не равен «равен»). –

+2

@Adam Arold Нет, «ref» не означает ссылку, это означает отражение. См. Исходный код в 'org.mockito.Matchers'. – John29

+0

Это не меняет того факта, что он не работает. Я попробовал. –

9

Это ответ на основании answer from iraSenthil, но с аннотацией (Captor). На мой взгляд, имеет некоторые преимущества:

  • он короче
  • легче читать
  • он может обрабатывать дженерики без предупреждений

Пример:

@RunWith(MockitoJUnitRunner.class) 
public class SomeTest{ 

    @Captor 
    private ArgumentCaptor<List<SomeType>> captor; 

    //... 

    @Test 
    public void shouldTestArgsVals() { 
     //... 
     verify(mockedObject).someMethodOnMockedObject(captor.capture()); 

     assertThat(captor.getValue().getXXX(), is("expected")); 
    } 
} 
+0

Ссылка "Captor" отключена – Thermech

+1

@Thermech thx, теперь исправлено :) –

+0

Это будет работать только для одного аргумента в параметрах. –

4

Если вы» re, используя Java 8, вы можете использовать выражения Lambda для соответствия.

import java.util.Optional; 
import java.util.function.Predicate; 

import org.hamcrest.BaseMatcher; 
import org.hamcrest.Description; 

public class LambdaMatcher<T> extends BaseMatcher<T> 
{ 
    private final Predicate<T> matcher; 
    private final Optional<String> description; 

    public LambdaMatcher(Predicate<T> matcher) 
    { 
     this(matcher, null); 
    } 

    public LambdaMatcher(Predicate<T> matcher, String description) 
    { 
     this.matcher = matcher; 
     this.description = Optional.ofNullable(description); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public boolean matches(Object argument) 
    { 
     return matcher.test((T) argument); 
    } 

    @Override 
    public void describeTo(Description description) 
    { 
     this.description.ifPresent(description::appendText); 
    } 
} 

Пример вызова

@Test 
public void canFindEmployee() 
{ 
    Employee employee = new Employee("John"); 
    company.addEmployee(employee); 

    verify(mockedDal).registerEmployee(argThat(new LambdaMatcher<>(e -> e.getName() 
                     .equals(employee.getName())))); 
} 

Подробнее: http://source.coveo.com/2014/10/01/java8-mockito/

0

Вы можете сослаться на следующее:

Mockito.verify(mockedObject).someMethodOnMockedObject(eq(desiredObject)) 

Это будет проверить, является ли метод mockedObject вызывается с desiredObject в качестве параметра ,

0

В javadoc для refEq указано, что проверка равенства неглубокая! Вы можете найти более подробную информацию по ссылке ниже:

[https://static.javadoc.io/org.mockito/mockito-core/2.2.29/org/mockito/ArgumentMatchers.html#refEq(T,%20java.lang.String...)][1]

«неглубоко равенство» проблема не может контролироваться при использовании других классов, которые не реализуют .equals() метод, класс «DefaultMongoTypeMapper» является пример, где метод .equals() не реализован.

org.springframework.beans.factory.support предлагает метод, который может генерировать определение компонента вместо создания экземпляра объекта, и его можно использовать, чтобы избавиться от ошибки сравнения.

genericBeanDefinition(DefaultMongoTypeMapper.class) 
         .setScope(SCOPE_SINGLETON) 
         .setAutowireMode(AUTOWIRE_CONSTRUCTOR) 
         .setLazyInit(false) 
         .addConstructorArgValue(null) 
         .getBeanDefinition() 

** "Определение боба только описание компонента, а не сам боба. описание фасоли должным образом реализовать равные() и хэш-код(), так что вместо того, чтобы создать новую DefaultMongoTypeMapper() мы дать определение, которое говорит весной, как это должно создать один»

в вашем примере, вы можете сделать somethong как этот

Mockito.verify(mockedObject) 
     .doSoething(genericBeanDefinition(YourClass.class).setA("a") 
     .getBeanDefinition()); 
0

решения выше на самом деле не работает в моем случае. Я не мог использовать ArgumentCaptor, поскольку метод вызывался несколько раз, и мне нужно было проверить его. Простой Matcher с «argThat» легко справился.

Пользовательские Сличитель

// custom matcher 
private class PolygonMatcher extends ArgumentMatcher<PolygonOptions> { 
    private int fillColor; 
    public PolygonMatcher(int fillColor) { 
     this.fillColor = fillColor; 
    } 

    @Override 
    public boolean matches(Object argument) { 
     if (!(argument instanceof PolygonOptions)) return false; 
     PolygonOptions arg = (PolygonOptions)argument; 
     return Color.red(arg.getFillColor()) == Color.red(fillColor) 
       && Color.green(arg.getFillColor()) == Color.green(fillColor) 
       && Color.blue(arg.getFillColor()) == Color.blue(fillColor); 
    } 
} 

Test Runner

// do setup work setup 
// 3 light green polygons 
int green = getContext().getResources().getColor(R.color.dmb_rx_bucket1); 
verify(map, times(3)).addPolygon(argThat(new PolygonMatcher(green))); 

// 1 medium yellow polygons 
int yellow = getContext().getResources().getColor(R.color.dmb_rx_bucket4); 
    verify(map, times(1)).addPolygon(argThat(new PolygonMatcher(yellow))); 

// 3 red polygons 
int orange = getContext().getResources().getColor(R.color.dmb_rx_bucket5); 
verify(map, times(3)).addPolygon(argThat(new PolygonMatcher(orange))); 

// 2 red polygons 
int red = getContext().getResources().getColor(R.color.dmb_rx_bucket7); 
verify(map, times(2)).addPolygon(argThat(new PolygonMatcher(red))); 
Смежные вопросы