একটি উপহাস পদ্ধতি তৈরি করার মাধ্যমে এটিকে দেওয়া একটি যুক্তি ফিরিয়ে দেওয়া


673

একটি পদ্ধতি স্বাক্ষর বিবেচনা করুন:

public String myFunction(String abc);

মকিটো পদ্ধতিটি যে স্ট্রিংটি পেয়েছে একই স্ট্রিংটি ফিরে আসতে সহায়তা করতে পারে?


ঠিক আছে, সাধারণভাবে কোনও জাভা বিদ্রূপের কাঠামো সম্পর্কে কীভাবে ... অন্য যে কোনও কাঠামোর সাথে এটি সম্ভব, বা আমার যে আচরণটি চান তা নকল করার জন্য আমার কেবল একটি বোবা স্টাব তৈরি করা উচিত?
অভিজিৎ কাশনিয়া

উত্তর:


1001

আপনি মকিতোতে একটি উত্তর তৈরি করতে পারেন। ধরা যাক, আমাদের একটি অ্যাপ্লিকেশন নামক একটি ইন্টারফেস রয়েছে যার সাথে একটি পদ্ধতি myFunction রয়েছে।

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

মকিতো ১.৯.৫ এবং জাভা ৮, যেহেতু আপনি ল্যাম্বডা এক্সপ্রেশনও ব্যবহার করতে পারেন:

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

1
এটিও আমি খুঁজছিলাম। ধন্যবাদ! যদিও আমার সমস্যাটি ছিল অন্যরকম। আমি একটি অধ্যবসায় পরিষেবা (ইজেবি) উপহাস করতে চাই যা বস্তুগুলি সঞ্চয় করে এবং নাম হিসাবে তাদের ফিরিয়ে দেয়।
মিগু

7
আমি একটি অতিরিক্ত ক্লাস তৈরি করেছি যা উত্তরের ক্রমটি মোড়ানো। সুতরাং কোডটি পড়ছেwhen(...).then(Return.firstParameter())
স্পেসট্রাকার

69
জাভা 8 lambdas সঙ্গে এটি প্রথম আর্গুমেন্ট ফিরতে, এমনকি নির্দিষ্ট বর্গ, অর্থাত জন্য নৈশভোজ সহজ 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ক্লাসে স্থির , যা মকিতো ১.৯.৫ এ নতুন; সুতরাং আপনার সঠিক স্ট্যাটিক আমদানি লাগবে।


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>)" কল করার চেষ্টা করার সময় 'ফু (জাভা.লং। স্ট্রিং) এ প্রয়োগ করা যাবে না .থ্যি রিটারন (নতুন ফু (রিটার্নফর্স্টআরজি ())
লু 55

বিগত বছরগুলিতে আমার এই উত্তরটি বার বার বার বার গুগল করা দরকার, যেহেতু আমি "অতিরিক্তি উত্তর" মনে করতে পারি না এবং আমার খুব কমই এর প্রয়োজন হয় need তারপরে আমি আশ্চর্য হই যে কীভাবে হেক আমি সেই দৃশ্যাবলীটি তৈরি করতে পারি কারণ আমি প্রয়োজনীয়তা নির্ভরতাগুলি খুঁজে পাচ্ছি না। এটি কি কেবল মকিতোতে সরাসরি যুক্ত করা যায়নি? : /
বেয়ারুস

2
স্টিভের উত্তর আরও জেনেরিক। এটি কেবল আপনাকে কাঁচা যুক্তি ফিরিয়ে আনতে দেয়। আপনি যদি সেই যুক্তিটি প্রক্রিয়া করতে চান এবং ফলাফলটি ফিরে আসতে চান তবে স্টিভের উত্তর বিধিগুলি রয়েছে। তারা উভয় দরকারী হিসাবে আমি উভয় upvated।
akostadinov

এফওয়াইআই, আমদানি করতে হবে 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?
ভাইকিংস্টিভ

1
.getArgumentAt (..) আমার জন্য পাওয়া যায় নি তবে .getArgument (1) কাজ করেছে (mockito 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

এটি বেশ পুরানো প্রশ্ন তবে আমি এখনও প্রাসঙ্গিক বলে মনে করি। এছাড়াও গৃহীত উত্তরটি কেবল স্ট্রিংয়ের পক্ষে কাজ করে। ইতিমধ্যে মকিতো ২.১ রয়েছে এবং কিছু আমদানি পরিবর্তিত হয়েছে, তাই আমি আমার বর্তমান উত্তরটি ভাগ করতে চাই:

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

আরও হেরফের / চেকিং / যাই হোক না কেন, যুক্তির মানটি আর্গুমেন্টের মাধ্যমে স্পষ্টতই অ্যাক্সেসযোগ্য checking


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

আপনি আরগমেন্ট ক্যাপ্টর ব্যবহার করে এটি অর্জন করতে পারেন

আপনি যেমন শিম ফাংশন আছে কল্পনা।

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?).আমার উদাহরণে এটি কাজ করছে। ২. দুঃখিত, আপনি যে পয়েন্টটি তৈরি করার চেষ্টা করছেন তাতে আমি পরিষ্কার নই। উত্তরটি ওপির প্রশ্নের সাথে সুনির্দিষ্ট।
সিরিল চেরিয়ান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.