एक नकली विधि बनाने से एक तर्क वापस आ जाता है जो इसे पारित किया गया था


673

एक विधि हस्ताक्षर पर विचार करें जैसे:

public String myFunction(String abc);

क्या मॉकिटो उसी स्ट्रिंग को वापस करने में मदद कर सकता है जो प्राप्त विधि है?


ठीक है, सामान्य रूप से किसी भी जावा मॉकिंग ढांचे के बारे में कैसे ... क्या यह किसी भी अन्य ढांचे के साथ संभव है, या मुझे जो व्यवहार चाहिए, उसकी नकल करने के लिए मुझे केवल एक बेवकूफ बनाना चाहिए?
अभिजीत कासनिया

जवाबों:


1001

आप मॉकिटो में एक उत्तर बना सकते हैं। चलिए मान लेते हैं, हमारे पास एक एप्लीकेशन है जिसका नाम है एप्लीकेशन विथ ए मेथफंक्शन।

public interface Application {
  public String myFunction(String abc);
}

यहाँ एक मॉकिटो उत्तर के साथ परीक्षण विधि है:

public void testMyFunction() throws Exception {
  Application mock = mock(Application.class);
  when(mock.myFunction(anyString())).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
      Object[] args = invocation.getArguments();
      return (String) args[0];
    }
  });

  assertEquals("someString",mock.myFunction("someString"));
  assertEquals("anotherString",mock.myFunction("anotherString"));
}

मॉकिटो 1.9.5 और जावा 8 के बाद से, आप लैम्बडा एक्सप्रेशन का भी उपयोग कर सकते हैं:

when(myMock.myFunction(anyString())).thenAnswer(i -> i.getArguments()[0]);

1
यह वही है जिसकी मुझे तलाश थी। धन्यवाद! मेरी समस्या अलग थी, हालाँकि। मैं एक दृढ़ता सेवा (ईजेबी) का मजाक उड़ाना चाहता हूं जो वस्तुओं को संग्रहीत करती है और उन्हें नाम से लौटाती है।
मिगू

7
मैंने एक अतिरिक्त वर्ग बनाया जो उत्तर के निर्माण को लपेटता है। तो कोड की तरह पढ़ता हैwhen(...).then(Return.firstParameter())
SpaceTrucker

69
जावा 8 लैम्ब्डा के साथ, पहले तर्क को वापस करना आसान है, यहां तक ​​कि विशिष्ट वर्ग के लिए भी when(foo(any()).then(i -> i.getArgumentAt(0, Bar.class))। और आप बस एक विधि संदर्भ का उपयोग कर सकते हैं और वास्तविक विधि को कॉल कर सकते हैं।
पावेल डिडा

यह मेरी समस्या को एक विधि के साथ हल करता है Iterator<? extends ClassName>जो एक thenReturn()बयान में सभी प्रकार की कास्ट समस्याओं का कारण बनता है ।
माइकल शोप्सिन

16
जावा 8 और मॉकिटो <1.9.5 के साथ तो पावेल का उत्तर बन गयाwhen(foo(any()).thenAnswer(i -> i.getArguments()[0])
ग्रीम मॉस

566

यदि आपके पास मॉकिटो 1.9.5 या उच्चतर है, तो एक नया स्टैटिक तरीका है जो Answerआपके लिए ऑब्जेक्ट बना सकता है । आपको कुछ लिखने की जरूरत है

import static org.mockito.Mockito.when;
import static org.mockito.AdditionalAnswers.returnsFirstArg;

when(myMock.myFunction(anyString())).then(returnsFirstArg());

या वैकल्पिक रूप से

doAnswer(returnsFirstArg()).when(myMock).myFunction(anyString());

ध्यान दें कि returnsFirstArg()विधि AdditionalAnswersकक्षा में स्थिर है , जो मॉकिटो 1.9.5 के लिए नया है; इसलिए आपको सही स्थैतिक आयात की आवश्यकता होगी।


17
नोट: यह है when(...).then(returnsFirstArg()), मैंने गलती से when(...).thenReturn(returnsFirstArg())जो दिया थाjava.lang.ClassCastException: org.mockito.internal.stubbing.answers.ReturnsArgumentAt cannot be cast to
बेनेडिकट कोप्पेल

1
नोट: रिटर्नफर्स्टअर्ग () उत्तर <> तर्क के मूल्य के बजाय देता है। गॉट (org.mockito.stubbing.Answer <java.lang.Object>) .thenReturn (नई फू (returnsFirstArg ())) कॉल करने के लिए कोशिश करते हुए '' फू (java.lang.String) को लागू नहीं किया जा सकता है '
Lu55

मुझे पिछले वर्षों के लिए बार-बार इस उत्तर को बार-बार गूगल करने की आवश्यकता है, क्योंकि मुझे अभी "एडिशनल" याद नहीं आ रहे हैं और मुझे इसकी बहुत कम आवश्यकता है। तब मुझे आश्चर्य होता है कि मैं उस परिदृश्य को कैसे बना सकता हूं क्योंकि मुझे आवश्यक निर्भरता नहीं मिल रही है। क्या इसे सीधे सीधे मॉकिटो में नहीं जोड़ा जा सकता है? : /
BAERUS

2
स्टीव का जवाब अधिक सामान्य है। यह केवल आपको कच्चे तर्क को वापस करने की अनुमति देता है। यदि आप उस तर्क को संसाधित करना चाहते हैं और परिणाम वापस करना चाहते हैं, तो स्टीव के उत्तर नियम। मैंने दोनों को उतारा क्योंकि वे दोनों उपयोगी हैं।
akostadinov

FYI करें, हमें आयात करना है static org.mockito.AdditionalAnswers.returnsFirstArg। यह रिटर्न का उपयोग करने के लिए। इसके अलावा, मैं when(myMock.myFunction(any())).then(returnsFirstArg())
मॉकिटो

77

जावा 8 के साथ मॉकिटो के पुराने संस्करण के साथ एक-पंक्ति उत्तर बनाना संभव है:

when(myMock.myFunction(anyString()).then(i -> i.getArgumentAt(0, String.class));

बेशक यह AdditionalAnswersडेविड वैलेस द्वारा सुझाए गए उपयोग के रूप में उतना उपयोगी नहीं है , लेकिन यदि आप "मक्खी पर" तर्क को बदलना चाहते हैं तो यह उपयोगी हो सकता है।


1
प्रतिभाशाली। धन्यवाद। यदि तर्क है long, तो क्या यह अभी भी मुक्केबाजी के साथ काम कर सकता है और Long.class?
9

1
.getArgumentAt (..) मेरे लिए नहीं मिला था लेकिन .getArgument (1) काम किया (मॉकिटो 2.6.2)
कर्टिस

41

मुझे भी इसी तरह की समस्या थी। लक्ष्य एक ऐसी सेवा का मजाक उड़ाना था जो वस्तुओं को बनाए रखता है और उन्हें उनके नाम से वापस कर सकता है। सेवा इस तरह दिखती है:

public class RoomService {
    public Room findByName(String roomName) {...}
    public void persist(Room room) {...}
}

सर्विस मॉक रूम इंस्टेंस को स्टोर करने के लिए मैप का उपयोग करता है।

RoomService roomService = mock(RoomService.class);
final Map<String, Room> roomMap = new HashMap<String, Room>();

// mock for method persist
doAnswer(new Answer<Void>() {
    @Override
    public Void answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            Room room = (Room) arguments[0];
            roomMap.put(room.getName(), room);
        }
        return null;
    }
}).when(roomService).persist(any(Room.class));

// mock for method findByName
when(roomService.findByName(anyString())).thenAnswer(new Answer<Room>() {
    @Override
    public Room answer(InvocationOnMock invocation) throws Throwable {
        Object[] arguments = invocation.getArguments();
        if (arguments != null && arguments.length > 0 && arguments[0] != null) {
            String key = (String) arguments[0];
            if (roomMap.containsKey(key)) {
                return roomMap.get(key);
            }
        }
        return null;
    }
});

अब हम इस मॉक पर अपने परीक्षण चला सकते हैं। उदाहरण के लिए:

String name = "room";
Room room = new Room(name);
roomService.persist(room);
assertThat(roomService.findByName(name), equalTo(room));
assertNull(roomService.findByName("none"));

34

जावा 8 के साथ, स्टीव का जवाब बन सकता है

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
    invocation -> {
        Object[] args = invocation.getArguments();
        return args[0];
    });

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}

संपादित करें: और भी छोटा:

public void testMyFunction() throws Exception {
    Application mock = mock(Application.class);
    when(mock.myFunction(anyString())).thenAnswer(
        invocation -> invocation.getArgument(0));

    assertEquals("someString", mock.myFunction("someString"));
    assertEquals("anotherString", mock.myFunction("anotherString"));
}

6

यह एक बहुत पुराना सवाल है, लेकिन मुझे लगता है कि अभी भी प्रासंगिक है। इसके अलावा स्वीकृत उत्तर केवल स्ट्रिंग के लिए काम करता है। इस बीच मॉकिटो 2.1 है और कुछ आयात बदल गए हैं, इसलिए मैं अपना वर्तमान जवाब साझा करना चाहूंगा:

import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@Mock
private MyClass myClass;

// this will return anything you pass, but it's pretty unrealistic
when(myClass.myFunction(any())).then(returnsFirstArg());
// it is more "life-like" to accept only the right type
when(myClass.myFunction(any(ClassOfArgument.class))).then(returnsFirstArg());

MyClass.myFunction लगेगा:

public class MyClass {
    public ClassOfArgument myFunction(ClassOfArgument argument){
        return argument;
    }  
}

4

मैं कुछ इसी तरह का उपयोग करता हूं (मूल रूप से यह समान दृष्टिकोण है)। कभी-कभी कुछ इनपुट के लिए मॉक ऑब्जेक्ट रिटर्न पूर्व-परिभाषित आउटपुट होना उपयोगी होता है। यह इस प्रकार है:

private Hashtable<InputObject,  OutputObject> table = new Hashtable<InputObject, OutputObject>();
table.put(input1, ouput1);
table.put(input2, ouput2);

...

when(mockObject.method(any(InputObject.class))).thenAnswer(
       new Answer<OutputObject>()
       {
           @Override
           public OutputObject answer(final InvocationOnMock invocation) throws Throwable
           {
               InputObject input = (InputObject) invocation.getArguments()[0];
               if (table.containsKey(input))
               {
                   return table.get(input);
               }
               else
               {
                   return null; // alternatively, you could throw an exception
               }
           }
       }
       );

4

आप तर्क का मूल्यांकन करने के लिए परीक्षण में तर्क और तर्क देने के लिए ArgumentCaptor के साथ संयोजन में सत्यापन () का उपयोग करना चाह सकते हैं:

ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
verify(mock).myFunction(argument.capture());
assertEquals("the expected value here", argument.getValue());

तर्क का मूल्य स्पष्ट रूप से तर्क के माध्यम से सुलभ है। आगे के हेरफेर / जाँच / जो कुछ भी हो, के लिए मत भूलना।


3

यह थोड़ा पुराना है, लेकिन मैं यहां आया था क्योंकि मेरे पास एक ही मुद्दा था। मैं JUnit का उपयोग कर रहा हूं, लेकिन इस बार मजाक के साथ कोटलिन ऐप में। मैं जावा समकक्ष के संदर्भ और तुलना के लिए यहां एक नमूना पोस्ट कर रहा हूं:

@Test
fun demo() {
  // mock a sample function
  val aMock: (String) -> (String) = mockk()

  // make it return the same as the argument on every invocation
  every {
    aMock.invoke(any())
  } answers {
    firstArg()
  }

  // test it
  assertEquals("senko", aMock.invoke("senko"))
  assertEquals("senko1", aMock.invoke("senko1"))
  assertNotEquals("not a senko", aMock.invoke("senko"))
}

2

आप ArgumentCaptor का उपयोग करके इसे प्राप्त कर सकते हैं

कल्पना कीजिए कि आपके पास सेम फंक्शन है।

public interface Application {
  public String myFunction(String abc);
}

फिर अपनी परीक्षा कक्षा में:

//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);


when(mock.myFunction(param.capture())).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
      return param.getValue();//return the captured value.
    }
  });

या यदि आप लैम्ब्डा के प्रशंसक हैं तो बस करें:

//Use ArgumentCaptor to capture the value
ArgumentCaptor<String> param = ArgumentCaptor.forClass(String.class);


when(mock.myFunction(param.capture()))
    .thenAnswer((invocation) -> param.getValue());

सारांश: दिए गए पैरामीटर को कैप्चर करने के लिए, तर्क-वितर्क का उपयोग करें। बाद में जवाब में getValue का उपयोग करके कैप्चर किया गया मान लौटाएं।


यह काम नहीं करता है (अब?)। डॉक्स के बारे में: इस पद्धति का उपयोग सत्यापन के अंदर किया जाना चाहिए। इसका मतलब है कि आप सत्यापन विधि का उपयोग करते समय केवल मूल्य पर कब्जा कर सकते हैं
मुहम्मद मिसिर

1. This doesn´t work (anymore?).मुझे यकीन नहीं है कि आपके द्वारा मेरे उदाहरण पर काम करने का क्या मतलब है । 2. क्षमा करें, मैं उस बिंदु पर स्पष्ट नहीं हूं जिसे आप बनाने की कोशिश कर रहे हैं। उत्तर ओपी के प्रश्न के लिए विशिष्ट है।
सिरिल चेरियन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.