Mockito ile nesne özniteliği değerini doğrulama


264

Mockito ile alay etmek istediğim bir yöntem çağrım var. Başlangıç ​​olarak, yöntemin çağrılacağı bir nesne örneği oluşturdum ve enjekte ettim. Amacım yöntem çağrısındaki nesnelerden birini doğrulamak.

Mockito'nun sahte yöntem çağrıldığında nesneyi ve niteliklerini doğrulamanıza veya doğrulamasına izin vermenin bir yolu var mı?

misal

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

Bunu yapmak yerine, anyObject()argüman nesnesinin belirli alanlar içerdiğini kontrol etmek istiyorum

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

Bu durumlarda mockito kullanmaya alternatif olarak, mockedObject sınıfını genişleten ve nesneyi daha sonra karşılaştırmak üzere kaydetmek için someMethodOnMockedObject öğesini geçersiz kılan özel bir saplama oluşturmayı düşünebilirsiniz.
Gönen

Yanıtlar:


540

Mockito'ya eklenen yeni özellik bunu daha da kolaylaştırıyor,

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

Mockito belgelerine bir göz atın


Birden fazla parametre olduğunda ve yalnızca tek bir parametrenin yakalanması isteniyorsa, diğer ArgumentMatcher'ları kullanarak diğer argümanları geri alın:

verify(mock).doSomething(eq(someValue), eq(someOtherValue), argument.capture());
assertEquals("John", argument.getValue().getName());

1
yönteminizde birden fazla bağımsız değişken varsa Eşleştiriciler'i diğer tüm bağımsız değişkenler için de kullanmalısınız. akcasoy.wordpress.com/tag/argumentcaptor
robsonrosa

1
Birden fazla argüman varsa ne olur? İlgilendiğiniz kesin olanı nasıl belirtirsiniz?
IgorGanapolsky

2
@IgorGanapolsky Yapmanız gereken doSomething için ikinci bir String parametresi varsayarsak: verify (mock) .doSomething (argument.capture (), anyString ());
GreenTurtle

tüm bağımsız değişkenler için eşleştirici kullanma ihtiyacı yalnızca standart tüm veya hiçbir eşleştirici kullanım spesifikasyonuna göre yapılır.
Charney Kaye

54

Bir argüman nesnesini doğrulamanın en kolay yolunun refEqyöntemi kullanmak olduğunu düşünüyorum :

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

equals()Yansıma kullanılmadığı için nesne uygulanmasa bile kullanılabilir. Bazı alanları karşılaştırmak istemiyorsanız, adlarını bağımsız değişken olarak ekleyin refEq.


1
Bu çok zarif bir yol ama maalesef org.mockito.Matchers artık kullanımdan kaldırıldı
ihebiheb

5
@ihebiheb ArgumentMatchers'a taşındı
Michael

48

ArgumentCaptorKullanmak istemiyorsanız (örneğin, stubbing kullandığınız için) başka bir olasılık Hamcrest Matchers'ı Mockito ile birlikte kullanmaktır.

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

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

2
Sidenote: sınıfla Matchersaynı kod satırını yazmak org.mockito.Matchers, sahte işlev parametresinin basitçe eşleşmediğini belirten yanıltıcı bir istisna attığından paketin doğru olduğundan emin olun .
buer

1
Modern Mockito versiyonlarında, öyle MockitoHamcrest.argThat()ve değilMockito.argThat()
Roman Puchkovskiy

17

Bu, iraSenthil'in cevabına dayanan ama ek açıklama ile verilen cevaptır ( Captor ). Bence bazı avantajları var:

  • daha kısa
  • okumak daha kolay
  • uyarı yapmadan jenerik ilaçlarla başa çıkabilir

Misal:

@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"));
    }
}

Bu sadece parametrelerde tek bir argüman için işe yarayacaktır.
IgorGanapolsky

Birden fazla argüman için bir esir kullanabilirsiniz. Birden fazla argüman yakalarsanız, tüm sonuçları listeleyebilirsiniz captor.getAllValues(). captor.getValue()Yanıtta kullanılan yöntem son sonucu verir.
Walery Strauch

11

Java 8 kullanıyorsanız, eşleştirmek için Lambda ifadelerini kullanabilirsiniz.

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);
    }
}

Örnek çağrı

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

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

Daha fazla bilgi: http://source.coveo.com/2014/10/01/java8-mockito/


5

Yukarıdaki çözümler benim durumumda gerçekten işe yaramadı. Yöntem birkaç kez çağrıldığından ArgumentCaptor kullanamadım ve her birini doğrulamak gerekiyordu. "ArgThat" ile basit bir Matcher kolayca hile yaptı.

Özel Eşleştirici

// 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 Koşucusu

// 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)));

3

Ve koltin'de çok güzel ve temiz bir çözüm com.nhaarman.mockito_kotlin

verify(mock).execute(argThat {
    this.param = expected
})

1

Aşağıdakilere başvurabilirsiniz:

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

Bu, mockedObject yönteminin arananObject ile parametre olarak çağrılıp çağrılmadığını doğrular.


1

Bunu yapmanın başka bir kolay yolu:

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;
            }
        }));

0

RefEq için javadoc eşitlik kontrolünün sığ olduğunu belirtti! Daha fazla ayrıntıyı aşağıdaki bağlantıda bulabilirsiniz:

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

.equals () yöntemini uygulamayan diğer sınıfları kullandığınızda "sığ eşitlik" sorunu denetlenemez, "DefaultMongoTypeMapper" sınıfı .equals () yönteminin uygulanmadığı bir örnektir.

org.springframework.beans.factory.support, nesnenin bir örneğini oluşturmak yerine bir fasulye tanımı oluşturabilen bir yöntem sunar ve Karşılaştırma Hatası'ndan kurtulmak için kullanılabilir.

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

** "Fasulye tanımı sadece fasulyenin değil, fasulyenin kendisinin bir tanımıdır. Fasulye açıklamaları eşittir eşittir () ve hashCode (), bu yüzden yeni bir DefaultMongoTypeMapper () oluşturmak yerine baharın nasıl olduğunu anlatan bir tanım sağlıyoruz. bir tane oluşturmalı "

Örneğinizde, böyle bir şey yapabilirsiniz

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

0

Yeni bir Matcher uygulama sınıfı oluşturmadan ve lambda ifadesini kullanmadan basitleştirilmiş bir çözüm:

        verify(mockObject).someMockMethod(argThat((SomeArgument arg) -> arg.fieldToMatch.equals(expectedFieldValue));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.