Проверьте значение атрибута объекта с помощью mockito - PullRequest
231 голосов
/ 17 июля 2009

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

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

Пример

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

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

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

Ответы [ 10 ]

476 голосов
/ 16 сентября 2011

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

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

Взгляните на документацию Mockito


В случае, когда имеется более одного параметра, и требуется захват только одного параметра, используйте другие ArgumentMatchers для переноса остальных аргументов:

verify(mock).doSomething(eq(someValue), eq(someOtherValue), argument.capture());
assertEquals("John", argument.getValue().getName());
53 голосов
/ 30 мая 2014

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

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

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

43 голосов
/ 01 мая 2012

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

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

Mockito.verify(mockedObject).someMethodOnMockedObject(Mockito.argThat(
    Matchers.<SomeObjectAsArgument>hasProperty("propertyName", desiredValue)));
15 голосов
/ 09 апреля 2015

Это ответ на основе ответа от 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"));
    }
}
8 голосов
/ 17 марта 2016

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

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/

4 голосов
/ 10 ноября 2017

Приведенные выше решения не сработали в моем случае. Я не мог использовать 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)));
2 голосов
/ 13 февраля 2019

Еще один простой способ сделать это:

import org.mockito.BDDMockito;    
import static org.mockito.Matchers.argThat;
import org.mockito.ArgumentMatcher;

BDDMockito.verify(mockedObject)
        .someMethodOnMockedObject(argThat(new ArgumentMatcher<TypeOfMethodArg>() {

            @Override
            public boolean matches(Object argument) {
                final TypeOfMethodArg castedArg = (TypeOfMethodArg) argument;

                // Make your verifications and return a boolean to say if it matches or not
                boolean isArgMarching = true;

                return isArgMarching;
            }
        }));
2 голосов
/ 06 декабря 2018

И очень хороший и чистый раствор в колтинах от com.nhaarman.mockito_kotlin

verify(mock).execute(argThat {
    this.param = expected
})
1 голос
/ 07 декабря 2016

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

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

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

0 голосов
/ 25 февраля 2017

В 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()

** "Определение компонента - это только описание компонента, а не сам компонент. описания бина правильно реализуют equals () и hashCode (), поэтому вместо создания нового DefaultMongoTypeMapper () мы предоставляем определение, которое сообщает Spring, как он должен его создавать "*

В вашем примере вы можете сделать что-то вроде этого

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