मॉकिटो फ्रेमवर्क में @Mock
और क्या अंतर है @InjectMocks
?
मॉकिटो फ्रेमवर्क में @Mock
और क्या अंतर है @InjectMocks
?
जवाबों:
@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...
}
यह कैसे @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
विधि का व्यवहार है । अन्त में, का उपयोग कर @InjectMocks
Mockito रखा जाएगा कि 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>
।
आपके परीक्षण वर्ग में, परीक्षण किए गए वर्ग को एनोटेट किया जाना चाहिए @InjectMocks
। यह मॉकिटो बताता है कि किस वर्ग को नकली इंजेक्शन लगाना है:
@InjectMocks
private SomeManager someManager;
तब से, हम यह निर्दिष्ट कर सकते हैं कि कक्षा के अंदर कौन से विशिष्ट तरीके या ऑब्जेक्ट हैं, इस मामले में SomeManager
, उन्हें मोक्स के साथ प्रतिस्थापित किया जाएगा:
@Mock
private SomeDependency someDependency;
इस उदाहरण में, वर्ग के SomeDependency
अंदर का SomeManager
मजाक उड़ाया जाएगा।
@Mock
एनोटेशन संबंधित वस्तु का मजाक उड़ाता है।
@InjectMocks
एनोटेशन अंतर्निहित ऑब्जेक्ट को अलग-अलग (और प्रासंगिक) द्वारा बनाए गए मोक्स में इंजेक्ट करने की अनुमति देता है @Mock
।
दोनों पूरक हैं।
@InjectMocks
इस वर्ग के निर्माण और उस पर जासूसी करने के लिए उपयोग करने के बारे में सोच रहा था ।
उदाहरण के लिए
@Mock
StudentDao studentDao;
@InjectMocks
StudentService service;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
यहां हमें सेवा वर्ग के लिए DAO वर्ग की आवश्यकता है। इसलिए, हम इसे मॉक करते हैं और इसे सेवा वर्ग के उदाहरण में इंजेक्ट करते हैं। इसी तरह, स्प्रिंग फ्रेमवर्क में सभी @Autowired बीन्स को @Mock द्वारा jUnits में मॉक किया जा सकता है और @InjectMocks के माध्यम से आपके बीन में इंजेक्ट किया जा सकता है ।
MockitoAnnotations.initMocks(this)
विधि इन मोक्स को इनिशियलाइज़ करती है और उन्हें हर टेस्ट विधि के लिए इंजेक्ट करती है इसलिए इसे setUp()
विधि में कहा जाना चाहिए ।
एक "मॉकिंग फ्रेमवर्क", जो मॉकिटो पर आधारित है, एक ऐसा ढांचा है जो आपको मॉक ऑब्जेक्ट्स बनाने की क्षमता देता है (पुराने शब्दों में इन ऑब्जेक्ट्स को शंट कहा जा सकता है, क्योंकि वे निर्भरता कार्यक्षमता के लिए शंट के रूप में काम करते हैं) दूसरे शब्दों में, एक मॉक। ऑब्जेक्ट का उपयोग उस वास्तविक ऑब्जेक्ट की नकल करने के लिए किया जाता है जिस पर आपका कोड निर्भर है, आप नकली फ्रेमवर्क के साथ एक प्रॉक्सी ऑब्जेक्ट बनाते हैं। अपने परीक्षणों में नकली वस्तुओं का उपयोग करके आप अनिवार्य रूप से सामान्य इकाई परीक्षण से एकीकृत परीक्षण तक जा रहे हैं
मॉकिटो एमआईटी लाइसेंस के तहत जारी जावा के लिए एक खुला स्रोत परीक्षण ढांचा है, यह एक "नकली रूपरेखा" है, जो आपको स्वच्छ और सरल एपीआई के साथ सुंदर परीक्षण लिखने की सुविधा देता है। जावा स्पेस में कई अलग-अलग मॉकिंग फ्रेमवर्क हैं, हालांकि अनिवार्य रूप से दो मुख्य प्रकार के मॉक ऑब्जेक्ट फ्रेमवर्क हैं, जिन्हें प्रॉक्सी के माध्यम से लागू किया जाता है और जिन्हें क्लास रीमैपिंग के माध्यम से लागू किया जाता है।
वसंत की तरह निर्भरता इंजेक्शन रूपरेखा आपको किसी भी कोड को संशोधित किए बिना अपनी प्रॉक्सी वस्तुओं को इंजेक्ट करने की अनुमति देती है, मॉक ऑब्जेक्ट को एक निश्चित विधि कहा जाता है और यह एक अपेक्षित परिणाम लौटाएगा।
@InjectMocks
एनोटेशन परीक्षण वस्तु दृष्टान्त और injects क्षेत्रों के साथ एनोटेट का दृष्टांत की कोशिश करता है @Mock
या @Spy
परीक्षण वस्तु के निजी क्षेत्रों में।
MockitoAnnotations.initMocks(this)
कॉल, परीक्षण ऑब्जेक्ट को रीसेट करता है और मॉक को फिर से इनिशियलाइज़ करता है, इसलिए इसे अपने @Before
/ @BeforeMethod
एनोटेशन पर याद रखें ।
@ टोम द्वारा बताए गए दृष्टिकोण के साथ एक लाभ यह है कि आपको 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...
}
इसका अच्छा अभ्यास है या नहीं, यह आपके एप्लिकेशन डिज़ाइन पर निर्भर करता है।
@Mock
बनाम के बारे में कई लोगों ने यहां एक शानदार विवरण दिया है @InjectMocks
। मुझे यह पसंद है, लेकिन मुझे लगता है कि हमारे परीक्षणों और एप्लिकेशन को इस तरह से लिखा जाना चाहिए कि हमें उपयोग करने की आवश्यकता न हो @InjectMocks
।
उदाहरणों के साथ आगे पढ़ने के लिए संदर्भ: https://tedvinke.wordpress.com/2014/02/13/mockito-why-you-should-not-use-injectmocks-annotation-to-autowire-fields/
@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(){
}
}
@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"));
}
हालांकि उपरोक्त उत्तर कवर किए गए हैं, मैंने अभी मिनट डिटेल जोड़ने की कोशिश की है जो मुझे गायब दिखाई दे रहा है। उनके पीछे का कारण (द क्यों)।
उदाहरण:
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>
}
}