@Mock और @InjectMocks के बीच अंतर


जवाबों:


542

@Mockएक नकली बनाता है। @InjectMocksवर्ग का एक उदाहरण बनाता है और इस उदाहरण में @Mock(या @Spy) एनोटेशन के साथ बनाए जाने वाले मोक्स को इंजेक्ट करता है ।

ध्यान दें कि आपको इन मोक्स का उपयोग @RunWith(MockitoJUnitRunner.class)या Mockito.initMocks(this)आरंभ करना होगा और उन्हें इंजेक्ट करना होगा।

@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {

    @InjectMocks
    private SomeManager someManager;

    @Mock
    private SomeDependency someDependency; // this will be injected into someManager

     //tests...

}

2
संक्षिप्त और संक्षिप्त उत्तर। सहायक भी;)
चकलादार असफ़ाक आरिफ़

क्या यह सकर्मक निर्भरता या केवल प्रत्यक्ष सदस्यों के लिए काम करता है?
पियरे थिबॉल्ट

@PierreThibault इंजेक्षन मॉक केवल प्रत्यक्ष सदस्यों के लिए काम करता है, लेकिन आप स्टब्स को स्थिर
टॉम

1
मुझे लगता है कि यह ऑनलाइन लेख के अधिकांश की तुलना में बहुत स्पष्ट है .... कि छोटी टिप्पणियां मेरी गांड को
बचाती हैं

मेरे पास कुछ आइटम हैं जो संदर्भ की तरह @Mock एनोटेशन द्वारा प्रदान नहीं किए जा सकते हैं। मैं इसे मुख्य वर्ग के लिए कैसे प्रदान कर सकता हूं?
महदी

220

यह कैसे @Mockऔर @InjectMocksकाम करता है पर एक नमूना कोड है ।

कहो हमारे पास Gameऔर Playerकक्षा है।

class Game {

    private Player player;

    public Game(Player player) {
        this.player = player;
    }

    public String attack() {
        return "Player attack with: " + player.getWeapon();
    }

}

class Player {

    private String weapon;

    public Player(String weapon) {
        this.weapon = weapon;
    }

    String getWeapon() {
        return weapon;
    }
}

जैसा कि आप देखते हैं, Gameवर्ग Playerको एक प्रदर्शन करने की आवश्यकता है attack

@RunWith(MockitoJUnitRunner.class)
class GameTest {

    @Mock
    Player player;

    @InjectMocks
    Game game;

    @Test
    public void attackWithSwordTest() throws Exception {
        Mockito.when(player.getWeapon()).thenReturn("Sword");

        assertEquals("Player attack with: Sword", game.attack());
    }

}

Mockito एक खिलाड़ी वर्ग का मज़ाक उड़ाएगा और यह प्रयोग whenऔर thenReturnविधि का व्यवहार है । अन्त में, का उपयोग कर @InjectMocksMockito रखा जाएगा कि Playerमें Game

ध्यान दें कि आपको कोई new Gameऑब्जेक्ट बनाने की आवश्यकता नहीं है । मॉकिटो आपके लिए इसे इंजेक्ट करेगा।

// you don't have to do this
Game game = new Game(player);

हमें @Spyएनोटेशन का उपयोग करके भी ऐसा ही व्यवहार मिलेगा । भले ही विशेषता नाम अलग हो।

@RunWith(MockitoJUnitRunner.class)
public class GameTest {

  @Mock Player player;

  @Spy List<String> enemies = new ArrayList<>();

  @InjectMocks Game game;

  @Test public void attackWithSwordTest() throws Exception {
    Mockito.when(player.getWeapon()).thenReturn("Sword");

    enemies.add("Dragon");
    enemies.add("Orc");

    assertEquals(2, game.numberOfEnemies());

    assertEquals("Player attack with: Sword", game.attack());
  }
}

class Game {

  private Player player;

  private List<String> opponents;

  public Game(Player player, List<String> opponents) {
    this.player = player;
    this.opponents = opponents;
  }

  public int numberOfEnemies() {
    return opponents.size();
  }

  // ...

ऐसा इसलिए है क्योंकि मॉकिटो Type Signatureगेम क्लास की जांच करेगा , जो है Playerऔर List<String>


16
इस उदाहरण के साथ यह स्वीकृत उत्तर होना चाहिए।
अन्नाकेलिन

4
मुझे लगता है कि यह भी सबसे अच्छा asnwer है
एव्गेनि Dorofeev

4
मुझे लगता है कि यह सबसे अच्छा जवाब ट्रिपल है।
हार्वे डेंट

1
मुझे कभी-कभी क्लास के लिए समझने और डिजाइन करने के लिए कठिन परीक्षण के साथ परीक्षण मिलता है। हालाँकि, यह उदाहरण अवलोकन प्रदान करने में बहुत मदद करता है।
चकलादार असफाक आरिफ़

1
बहुत धन्यवाद :) बेहतर स्पष्टीकरण के साथ इस बिंदु पर।
ऋषि

80

आपके परीक्षण वर्ग में, परीक्षण किए गए वर्ग को एनोटेट किया जाना चाहिए @InjectMocks। यह मॉकिटो बताता है कि किस वर्ग को नकली इंजेक्शन लगाना है:

@InjectMocks
private SomeManager someManager;

तब से, हम यह निर्दिष्ट कर सकते हैं कि कक्षा के अंदर कौन से विशिष्ट तरीके या ऑब्जेक्ट हैं, इस मामले में SomeManager, उन्हें मोक्स के साथ प्रतिस्थापित किया जाएगा:

@Mock
private SomeDependency someDependency;

इस उदाहरण में, वर्ग के SomeDependencyअंदर का SomeManagerमजाक उड़ाया जाएगा।


6
यह काम करेगा अगर someManager में अधिक है तो एक निर्माता? क्या होगा अगर कुछ प्रबंधक में 5 निर्माणकर्ता थे तो यह कैसे पता चलेगा कि आप किसका उपयोग करना चाहते हैं?
j2emanue

51

@Mock एनोटेशन संबंधित वस्तु का मजाक उड़ाता है।

@InjectMocksएनोटेशन अंतर्निहित ऑब्जेक्ट को अलग-अलग (और प्रासंगिक) द्वारा बनाए गए मोक्स में इंजेक्ट करने की अनुमति देता है @Mock

दोनों पूरक हैं।


1
क्या उन्हें एक ही वस्तु पर मिलकर इस्तेमाल किया जा सकता है?
इगोरगानापोलस्की 20

1
क्या आपके पास अपनी आवश्यकता का एक छोटा उदाहरण है?
मिक 378

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

1
कि तुम क्या देख रहे हो? stackoverflow.com/a/35969166/985949
मिक378

23
  • @ मॉक आपको उन कक्षाओं के लिए एक नकली कार्यान्वयन बनाता है जिनकी आपको आवश्यकता है।
  • @ InjectMock क्लास का एक उदाहरण बनाता है और एनोटेशन @Mock के साथ चिन्हित किए गए मक्स को इंजेक्ट करता है।

उदाहरण के लिए

@Mock
StudentDao studentDao;

@InjectMocks
StudentService service;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

यहां हमें सेवा वर्ग के लिए DAO वर्ग की आवश्यकता है। इसलिए, हम इसे मॉक करते हैं और इसे सेवा वर्ग के उदाहरण में इंजेक्ट करते हैं। इसी तरह, स्प्रिंग फ्रेमवर्क में सभी @Autowired बीन्स को @Mock द्वारा jUnits में मॉक किया जा सकता है और @InjectMocks के माध्यम से आपके बीन में इंजेक्ट किया जा सकता है ।

MockitoAnnotations.initMocks(this)विधि इन मोक्स को इनिशियलाइज़ करती है और उन्हें हर टेस्ट विधि के लिए इंजेक्ट करती है इसलिए इसे setUp()विधि में कहा जाना चाहिए ।

इस लिंक में मॉकिटो फ्रेमवर्क के लिए एक अच्छा ट्यूटोरियल है


13

एक "मॉकिंग फ्रेमवर्क", जो मॉकिटो पर आधारित है, एक ऐसा ढांचा है जो आपको मॉक ऑब्जेक्ट्स बनाने की क्षमता देता है (पुराने शब्दों में इन ऑब्जेक्ट्स को शंट कहा जा सकता है, क्योंकि वे निर्भरता कार्यक्षमता के लिए शंट के रूप में काम करते हैं) दूसरे शब्दों में, एक मॉक। ऑब्जेक्ट का उपयोग उस वास्तविक ऑब्जेक्ट की नकल करने के लिए किया जाता है जिस पर आपका कोड निर्भर है, आप नकली फ्रेमवर्क के साथ एक प्रॉक्सी ऑब्जेक्ट बनाते हैं। अपने परीक्षणों में नकली वस्तुओं का उपयोग करके आप अनिवार्य रूप से सामान्य इकाई परीक्षण से एकीकृत परीक्षण तक जा रहे हैं

मॉकिटो एमआईटी लाइसेंस के तहत जारी जावा के लिए एक खुला स्रोत परीक्षण ढांचा है, यह एक "नकली रूपरेखा" है, जो आपको स्वच्छ और सरल एपीआई के साथ सुंदर परीक्षण लिखने की सुविधा देता है। जावा स्पेस में कई अलग-अलग मॉकिंग फ्रेमवर्क हैं, हालांकि अनिवार्य रूप से दो मुख्य प्रकार के मॉक ऑब्जेक्ट फ्रेमवर्क हैं, जिन्हें प्रॉक्सी के माध्यम से लागू किया जाता है और जिन्हें क्लास रीमैपिंग के माध्यम से लागू किया जाता है।

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

@InjectMocksएनोटेशन परीक्षण वस्तु दृष्टान्त और injects क्षेत्रों के साथ एनोटेट का दृष्टांत की कोशिश करता है @Mockया @Spyपरीक्षण वस्तु के निजी क्षेत्रों में।

MockitoAnnotations.initMocks(this)कॉल, परीक्षण ऑब्जेक्ट को रीसेट करता है और मॉक को फिर से इनिशियलाइज़ करता है, इसलिए इसे अपने @Before/ @BeforeMethodएनोटेशन पर याद रखें ।


2
मैं यह नहीं कहूंगा कि "अपने परीक्षणों में नकली वस्तुओं का उपयोग करके आप अनिवार्य रूप से सामान्य इकाई परीक्षण से एकीकृत परीक्षण तक जा रहे हैं"। मेरे लिए, मॉकिंग को यूनिट-टेस्ट के क्रम में जांच की जाने वाली स्थिरता को अलग करना है। एकीकरण परीक्षण वास्तविक नहीं नकली निर्भरता का उपयोग करेगा।
पश्चिमीगुन

10

@ टोम द्वारा बताए गए दृष्टिकोण के साथ एक लाभ यह है कि आपको SomeManager में कोई भी निर्माणकर्ता बनाने की ज़रूरत नहीं है, और इसलिए ग्राहकों को इसे सीमित करने के लिए सीमित करना है।

@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {

    @InjectMocks
    private SomeManager someManager;

    @Mock
    private SomeDependency someDependency; // this will be injected into someManager

    //You don't need to instantiate the SomeManager with default contructor at all
   //SomeManager someManager = new SomeManager();    
   //Or SomeManager someManager = new SomeManager(someDependency);

     //tests...

}

इसका अच्छा अभ्यास है या नहीं, यह आपके एप्लिकेशन डिज़ाइन पर निर्भर करता है।


क्या होगा अगर कुछ प्रबंधक के पास 3 अलग-अलग निर्माता हैं, तो यह कैसे पता चलेगा कि किसका उपयोग करना है?
j2emanue

यदि आप इसका मजाक नहीं उड़ाते हैं, तो आप कुछ प्रबंधक पर सामान कैसे सत्यापित करेंगे?
इगोरगानापोलस्की 20

5

@Mockबनाम के बारे में कई लोगों ने यहां एक शानदार विवरण दिया है @InjectMocks। मुझे यह पसंद है, लेकिन मुझे लगता है कि हमारे परीक्षणों और एप्लिकेशन को इस तरह से लिखा जाना चाहिए कि हमें उपयोग करने की आवश्यकता न हो @InjectMocks

उदाहरणों के साथ आगे पढ़ने के लिए संदर्भ: https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/


1
यह एक दीर्घकालिक समाधान प्रतीत होता है।
विनायक दोरनाला

4

@Mockका उपयोग आश्रित सेम के संदर्भों को घोषित / मॉक करने के लिए @InjectMocksकिया जाता है , जबकि बीन का मजाक बनाने के लिए उपयोग किया जाता है जिसके लिए परीक्षण बनाया जा रहा है।

उदाहरण के लिए:

public class A{

   public class B b;

   public void doSomething(){

   }

}

कक्षा के लिए परीक्षा A:

public class TestClassA{

   @Mocks
   public class B b;

   @InjectMocks
   public class A a;

   @Test
   public testDoSomething(){

   }

}

4

@InjectMocks एनोटेशन का उपयोग मॉक फ़ील्ड को स्वचालित रूप से परीक्षण ऑब्जेक्ट में इंजेक्ट करने के लिए किया जा सकता है।

नीचे दिए गए उदाहरण में @InjectMocks ने मॉक डेटाफ़ॉर्म को डेटालाइंस में इंजेक्ट करने के लिए उपयोग किया है।

@Mock
Map<String, String> dataMap ;

@InjectMocks
DataLibrary dataLibrary = new DataLibrary();


    @Test
    public void whenUseInjectMocksAnnotation_() {
        Mockito.when(dataMap .get("aData")).thenReturn("aMeaning");

        assertEquals("aMeaning", dataLibrary .getMeaning("aData"));
    }

3

कि सूचना है कि @InjectMocksके बारे में किया जाना है पदावनत

Mateito 3/4 में हटाने के लिए @InjectMocks और शेड्यूल को अपग्रेड करें

और आप @ उत्तर का अनुसरण कर सकते हैं और इस पर लिंक कर सकते हैं :

क्यों आप Autowire फ़ील्ड के लिए InjectMocks एनोटेशन का उपयोग नहीं करना चाहिए


3

हालांकि उपरोक्त उत्तर कवर किए गए हैं, मैंने अभी मिनट डिटेल जोड़ने की कोशिश की है जो मुझे गायब दिखाई दे रहा है। उनके पीछे का कारण (द क्यों)।

यहां छवि विवरण दर्ज करें


उदाहरण:

Sample.java
---------------
    public class Sample{
        DependencyOne dependencyOne;
        DependencyTwo dependencyTwo;


        public SampleResponse methodOfSample(){
            dependencyOne.methodOne();
            dependencyTwo.methodTwo();

            ...

            return sampleResponse;
        }
    }

SampleTest.java
-----------------------
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassA.class})
public class SampleTest{

    @InjectMocks
    Sample sample;

    @Mock
    DependencyOne dependencyOne;

    @Mock
    DependencyTwo dependencyTwo;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    public void sampleMethod1_Test(){
        //Arrange the dependencies
        DependencyResponse dependencyOneResponse = Mock(sampleResponse.class);
        Mockito.doReturn(dependencyOneResponse).when(dependencyOne).methodOne();

        DependencyResponse dependencyTwoResponse = Mock(sampleResponse.class);
        Mockito.doReturn(dependencyOneResponse).when(dependencyTwo).methodTwo();

        //call the method to be tested
        SampleResponse sampleResponse = sample.methodOfSample() 

        //Assert
        <assert the SampleResponse here>
    }
}

संदर्भ

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.