मॉकिटो फ्रेमवर्क में @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विधि का व्यवहार है । अन्त में, का उपयोग कर @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>।
आपके परीक्षण वर्ग में, परीक्षण किए गए वर्ग को एनोटेट किया जाना चाहिए @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>
}
}