मॉकिटो के साथ ऑब्जेक्ट विशेषता मान सत्यापित करें


264

मेरे पास एक मेथड कॉल है जिसे मैं मॉकिटो के साथ मॉक करना चाहता हूं। शुरू करने के लिए मैंने एक ऑब्जेक्ट का एक उदाहरण बनाया और इंजेक्ट किया, जिस पर विधि को बुलाया जाएगा। मेरा उद्देश्य विधि कॉल में किसी एक वस्तु को सत्यापित करना है।

क्या कोई ऐसा तरीका है जो मॉकिटो आपको ऑब्जेक्ट को मुखर या सत्यापित करने की अनुमति देता है और यह विशेषता है जब मॉक विधि कहा जाता है?

उदाहरण

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

करने के बजाय anyObject()मैं यह जांचना चाहता हूं कि तर्क वस्तु में कुछ विशेष क्षेत्र शामिल हैं

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

इन मामलों में मॉकिटो का उपयोग करने के विकल्प के रूप में, आप एक कस्टम स्टब बनाने पर विचार कर सकते हैं, जो मॉकऑबजेक्ट के वर्ग को बढ़ाता है, और बाद की तुलना के लिए ऑब्जेक्ट को बचाने के लिए someMethodOnMockedObject को ओवरराइड करता है।
गॉनन I

जवाबों:


539

मॉकिटो में जोड़ा गया नया फीचर इसे और भी आसान बनाता है,

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

मॉकिटो प्रलेखन पर एक नज़र डालें


मामले में जब एक से अधिक पैरामीटर होते हैं, और केवल एकल परम पर कब्जा करना वांछित होता है, तो बाकी तर्क को लपेटने के लिए अन्य ArgumentMatchers का उपयोग करें:

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

1
यदि आपकी विधि में एक से अधिक तर्क हैं, तो आपको अन्य सभी तर्कों के लिए भी मिलानकर्ताओं का उपयोग करना होगा। akcasoy.wordpress.com/tag/argumentcaptor
robsonrosa

1
यदि कई तर्क हैं तो क्या होगा? आप जिस चीज में रुचि रखते हैं, उसे कैसे निर्दिष्ट करते हैं?
इगोरगानापोलस्की

2
@IgorGanapolsky doSomething के लिए एक दूसरे स्ट्रिंग पैरामीटर को मानते हुए आपको करने की आवश्यकता है: सत्यापन (मॉक) .doSomething (तर्क। अनुकूलन) (, anyString ());
ग्रीनटर्ल

सभी तर्कों के लिए मैचर्स का उपयोग करने की आवश्यकता पूरी तरह से मानक ऑल-ऑर-नो मैचर उपयोग युक्ति के अनुसार है।
चारनी काये

54

मुझे लगता है कि किसी तर्क वस्तु को सत्यापित करने का सबसे आसान तरीका refEqविधि का उपयोग करना है:

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

इसका उपयोग तब भी किया जा सकता है जब ऑब्जेक्ट लागू नहीं होता है equals(), क्योंकि प्रतिबिंब का उपयोग किया जाता है। यदि आप कुछ क्षेत्रों की तुलना नहीं करना चाहते हैं, तो उनके नाम को तर्क के रूप में जोड़ें refEq


1
यह एक बहुत ही सुंदर तरीका है लेकिन दुर्भाग्य से org.mockito.Matchers अब पदावनत हो गया है
ihebiheb

5
@ihebiheb यह ArgumentMatchers में स्थानांतरित हुआ
माइकल

48

एक और संभावना है, अगर आप ArgumentCaptor(उदाहरण के लिए, क्योंकि आप भी स्टबिंग का उपयोग कर रहे हैं) का उपयोग नहीं करना चाहते हैं, तो मॉकिटो के साथ संयोजन में हैमरेस्ट मैचर्स का उपयोग करना है।

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

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

2
सिडेनोट: सुनिश्चित करें कि Matchersपैकेज सही है, क्योंकि org.mockito.Matchersकक्षा के साथ कोड की एक ही पंक्ति लिखना एक भ्रामक अपवाद को फेंकता है जो बताता है कि नकली फ़ंक्शन का पैरामीटर बस मेल नहीं खाता है।
बुअर

1
कृपया ध्यान दें कि आधुनिक मॉकिटो संस्करणों में, यह है MockitoHamcrest.argThat()और नहींMockito.argThat()
रोमन Puchkovskiy

17

इस के आधार पर जवाब है iraSenthil से जवाब लेकिन एनोटेशन (साथ क़ैदी बनानेवाला )। मेरी राय में इसके कुछ फायदे हैं:

  • यह छोटा है
  • यह पढ़ना आसान है
  • यह चेतावनी के बिना जेनरिक को संभाल सकता है

उदाहरण:

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

यह केवल एक ही तर्क के लिए काम करेगा।
इगोरगानापोलस्की

आप एक से अधिक तर्कों के लिए एक कैप्चर का उपयोग कर सकते हैं। यदि आप एक से अधिक तर्क कैप्चर करते हैं, तो आप सभी परिणामों की सूची बना सकते हैं captor.getAllValues()captor.getValue()उत्तर में प्रयुक्त विधि अंतिम परिणाम देती है।
वलरी स्ट्रैच

11

यदि आप जावा 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/


5

उपरोक्त समाधान वास्तव में मेरे मामले में काम नहीं किया। मैं ArgumentCaptor का उपयोग नहीं कर सका क्योंकि विधि को कई बार बुलाया गया था और मुझे प्रत्येक को मान्य करने की आवश्यकता थी। "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);
    }
}

टेस्ट रनर

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

और कोल्टिन में से बहुत अच्छा और साफ समाधान com.nhaarman.mockito_kotlin

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

1

आप निम्नलिखित का उल्लेख कर सकते हैं:

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

यह सत्यापित करेगा कि पैरामीटर के रूप में वांछित विकल्प के साथ mockedObject की विधि कहा जाता है या नहीं।


1

ऐसा करने का एक और आसान तरीका:

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 के लिए javadoc ने उल्लेख किया कि समानता की जांच उथली है! आप नीचे दिए गए लिंक पर अधिक जानकारी पा सकते हैं:

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

"उथले समानता" समस्या को तब नियंत्रित नहीं किया जा सकता है जब आप अन्य वर्गों का उपयोग करते हैं, जो लागू नहीं करते हैं। () विधि, "DefaultMongoTypeMapper" वर्ग एक उदाहरण है जहाँ।

org.springframework.beans.factory.support एक ऐसी विधि प्रदान करता है जो वस्तु का एक उदाहरण बनाने के बजाय सेम परिभाषा उत्पन्न कर सकती है, और इसका उपयोग तुलना विफलता से छुटकारा पाने के लिए किया जा सकता है।

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

** "बीन परिभाषा केवल बीन का विवरण है, बीन ही नहीं। बीन विवरण समान रूप से बराबरी () और हैशकोड () को लागू करता है, इसलिए एक नया DefaultMongoTypeMapper () बनाने के बजाय हम एक परिभाषा प्रदान करते हैं जो यह बताता है कि यह वसंत कैसे है एक बनाना चाहिए ”

अपने उदाहरण में, आप कुछ इस तरह से कर सकते हैं

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

0

एक नया मिलान कार्यान्वयन वर्ग बनाए बिना और लैम्ब्डा अभिव्यक्ति का उपयोग किए बिना एक सरलीकृत समाधान:

        verify(mockObject).someMockMethod(argThat((SomeArgument arg) -> arg.fieldToMatch.equals(expectedFieldValue));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.