mockito ट्यूटोरियल
मॉकिटो के साथ शुरुआत करना
खोज…
टिप्पणियों
मॉकिटो एक जावा मॉकिंग फ्रेमवर्क है जिसका उद्देश्य सरल एपीआई का उपयोग करके एक पठनीय इकाई परीक्षणों को साफ करने की क्षमता प्रदान करना है। यह अन्य मॉकिंग फ्रेमवर्क से भिन्न है जो कि अपेक्षित रन-वेरी पैटर्न को छोड़ कर उपयोग करता है जो कि अधिकांश अन्य फ्रेमवर्क उपयोग करते हैं।
इसके बजाय यह केवल (गैर-अंतिम) कक्षाओं और इंटरफेस को मॉक करने का एक तरीका जानता है और लचीले तर्क मिलानकर्ताओं के आधार पर सत्यापित और स्टब करने की अनुमति देता है।
वर्तमान संस्करण 1.10.19 को मावेन का उपयोग करके सबसे अच्छा प्राप्त किया गया है
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
</dependency>
या ढाल
repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }
संस्करण 2 अभी भी बीटा में है।
संस्करण
संस्करण | मावेन सेंट्रल | रिलीज नोट्स | रिलीज़ की तारीख |
---|---|---|---|
2.1.0 | mockito कोर | परिवर्तन | 2016/10/04 |
1.10.19 | mockito कोर | परिवर्तन | 2014-12-31 |
मॉकिटो का उपयोग करके सरल इकाई परीक्षण
हम जिस वर्ग का परीक्षण करने जा रहे हैं वह है:
public class Service {
private Collaborator collaborator;
public Service(Collaborator collaborator) {
this.collaborator = collaborator;
}
public String performService(String input) {
return collaborator.transformString(input);
}
}
इसके सहयोगी हैं:
public class Collaborator {
public String transformString(String input) {
return doStuff();
}
private String doStuff() {
// This method may be full of bugs
. . .
return someString;
}
}
हमारे परीक्षण में, हम Collaborator
और उसके बगों से निर्भरता को तोड़ना चाहते हैं, इसलिए हम Collaborator
का मजाक उड़ाने जा रहे हैं:
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
public class ServiceTest {
@Test
public void testPerformService() throws Exception {
// Configure mock
Collaborator collaboratorMock = mock(Collaborator.class);
doReturn("output").when(collaboratorMock).transformString("input");
// Perform the test
Service service = new Service(collaboratorMock);
String actual = service.performService("input");
// Junit asserts
String expected = "output";
assertEquals(expected, actual);
}
}
मॉकिटो एनोटेशन का उपयोग करना
हम जिस वर्ग का परीक्षण करने जा रहे हैं वह है:
public class Service{
private Collaborator collaborator;
public Service(Collaborator collaborator){
this.collaborator = collaborator;
}
public String performService(String input){
return collaborator.transformString(input);
}
}
इसके सहयोगी हैं:
public class Collaborator {
public String transformString(String input){
return doStuff();
}
private String doStuff()
{
// This method may be full of bugs
. . .
return someString;
}
}
हमारे परीक्षण में, हम Collaborator
और इसकी बग्स से निर्भरता को तोड़ना चाहते हैं, इसलिए हम Collaborator
का मजाक बनाने जा रहे हैं। @Mock
एनोटेशन का उपयोग करना प्रत्येक परीक्षण के लिए विभिन्न उदाहरणों को बनाने के लिए एक सुविधाजनक तरीका है:
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class ServiceTest {
@Mock
private Collaborator collaboratorMock;
@InjectMocks
private Service service;
@Test
public void testPerformService() throws Exception {
// Configure mock
doReturn("output").when(collaboratorMock).transformString("input");
// Perform the test
String actual = service.performService("input");
// Junit asserts
String expected = "output";
assertEquals(expected, actual);
}
@Test(expected=Exception.class)
public void testPerformServiceShouldFail() throws Exception {
// Configure mock
doThrow(new Exception()).when(collaboratorMock).transformString("input");
// Perform the test
service.performService("input");
}
}
मॉकिटो निम्नलिखित क्रम में निर्भरता इंजेक्शन को हल करने की कोशिश करेगा:
- कंस्ट्रक्टर-आधारित इंजेक्शन - मोक्स को कंस्ट्रक्टर में अधिकांश तर्कों के साथ इंजेक्ट किया जाता है (यदि कुछ तर्क नहीं मिल सकते हैं, तो नल पास हो जाते हैं)। यदि किसी ऑब्जेक्ट को कंस्ट्रक्टर के माध्यम से सफलतापूर्वक बनाया गया था, तो कोई अन्य रणनीति लागू नहीं की जाएगी।
- सेटर-आधारित इंजेक्शन - मोक्स को प्रकार द्वारा इंजेक्ट किया जाता है। यदि एक ही प्रकार के कई गुण हैं, तो संपत्ति के नाम और नकली नामों का मिलान किया जाएगा।
- प्रत्यक्ष क्षेत्र इंजेक्शन - सेटर-आधारित इंजेक्शन के लिए समान।
ध्यान दें कि यदि कोई पूर्वोक्त रणनीति विफल रही तो किसी भी विफलता की सूचना नहीं है।
Mockito के नवीनतम संस्करण में इस तंत्र पर अधिक विस्तृत जानकारी के लिए नवीनतम @InjectMocks
से परामर्श करें।
स्थापना और सेटअप
स्थापना
mockito-core
को स्थापित करने का पसंदीदा तरीका mockito-core
पर निर्भरता को पसंद की निर्माण प्रणाली के साथ घोषित करना है। 22 जुलाई, 2016 तक, नवीनतम गैर-बीटा संस्करण 1.10.19 है, लेकिन 2.x को पहले से ही माइग्रेट करने के लिए प्रोत्साहित किया जाता है ।
Maven
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
Gradle
repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:1.+" }
इसमें mockito-all
भी है जिसमें मॉकिटो के अलावा हैमरेस्ट और ओबजेनेसिस भी हैं। यह मुख्य रूप से चींटी उपयोगकर्ताओं के लिए मावेन के माध्यम से दिया जाता है, लेकिन मॉकिटो 2.x में वितरण बंद कर दिया गया है।
आयात
org.mockito.Mockito
सुविधाओं के अधिकांश org.mockito.Mockito
स्थिर तरीके हैं। इस प्रकार, मॉकिटो को इस तरह से एक वर्ग में सांख्यिकीय रूप से आयात किया जा सकता है:
import static org.mockito.Mockito.*;
प्रलेखन प्रविष्टि बिंदु इस वर्ग के javadoc में स्थित है।
किसी वस्तु पर कुछ विधियों का मजाक उड़ाना
किसी वस्तु के बस कुछ तरीकों का मॉकिटो के स्पाई spy()
का उपयोग करके मजाक किया जा सकता है।
उदाहरण के लिए, कल्पना करें कि विधि वर्ग को काम करने के लिए कुछ वेब सेवा की आवश्यकता होती है।
public class UserManager {
List<User> users;
public UserManager() {
user = new LinkedLisk<User>();
}
public void addUser(User user) {
if (isValid(user)) {
user.add(user);
} else {
throw new NotValidUserException();
}
}
protected boolean isValid(User user) {
//some online web service to check if user is valid
}
public int numberOfUsers() {
return users.size();
}
}
addUser
लिए एक उपयोगी परीक्षण करने के लिए UserManager
विधि का परीक्षण किया जाना चाहिए। हालांकि, एक निर्भरता यहां पाई जाती है, isValid
को एक बाहरी वेब सेवा की आवश्यकता होती है जो हमारे कोड में निहित नहीं है। फिर, इस बाहरी निर्भरता को निष्प्रभावी किया जाना चाहिए।
इस मामले में, अगर आप केवल नकली isValid
आप के बाकी का परीक्षण करने में सक्षम हो जाएगा UserManager
तरीकों।
@Test
public void testAddUser() {
User user = mock(User.class);
UserManager manager = spy(new UserManager());
//it forces to manager.isValid to return true
doReturn(true).when(manager).isValid(anyObject());
manager.addUser(user);
assertTrue(manager.numberOfUsers(), 1);
}
आप आसानी से उस परिदृश्य की जाँच कर सकते हैं जहाँ user
मान्य नहीं है।
@Test(expectedExceptions = NotValidUserException.class)
public void testNotValidAddUser() {
User user = mock(User.class);
UserManager manager = spy(new UserManager());
//it forces to manager.isValid to return false
doReturn(false).when(manager).isValid(anyObject());
manager.addUser(user);
}
सरल न्यूनतम मॉकिटो टेस्ट
यह उदाहरण एक नकली ArrayList
का उपयोग करके न्यूनतम मॉकिटो परीक्षण दिखाता है:
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import java.util.ArrayList;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest
{
@Mock
ArrayList<String> listMock;
@Test
public void testAppend() {
// configure the mock to return "foobar" whenever "get()"
// is called on "listMock" with an int value as parameter
doReturn("foobar").when(listMock).get(anyInt());
String result = listMock.get(0);
assertEquals("foobar", result);
}
}
ArgumentCaptor के साथ तर्कों का सत्यापन करना
एक मॉक पर बताए गए तरीकों के लिए तर्कों को मान्य करने के लिए, ArgumentCaptor
वर्ग का उपयोग करें। यह आपको अपने परीक्षण पद्धति में तर्कों को निकालने और उन पर दावे करने की अनुमति देगा।
यह उदाहरण एक विधि का परीक्षण करता है जो किसी दिए गए आईडी के साथ उपयोगकर्ता के नाम को अपडेट करता है। विधि उपयोगकर्ता को लोड करती है, दिए गए मान के साथ name
विशेषता को अपडेट करती है और बाद में इसे सहेजती है। परीक्षण यह सत्यापित करना चाहता है कि save
विधि में दिया गया तर्क सही आईडी और नाम के साथ एक User
ऑब्जेक्ट है।
// This is mocked in the test
interface UserDao {
void save(User user);
}
@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
@Mock
UserDao userDao;
@Test
public void testSetNameForUser() {
UserService serviceUnderTest = new UserService(userDao);
serviceUnderTest.setNameForUser(1L, "John");
ArgumentCaptor<User> userArgumentCaptor = ArgumentCaptor.forClass(User.class);
verify(userDao).save(userArgumentCaptor.capture());
User savedUser = userArgumentCaptor.getValue();
assertTrue(savedUser.getId() == 1);
assertTrue(savedUser.getName().equals("John"));
}
}
ArgumentMatcher के साथ तर्क का सत्यापन
Mockito तर्कों को सत्यापित करने के लिए एक सार ArgumentMatcher<T>
वर्ग के साथ एक Matcher<T>
इंटरफ़ेस प्रदान करता है। यह ArgumentCaptor
तुलना में समान उपयोग-केस के लिए एक अलग दृष्टिकोण का उपयोग करता है। इसके अतिरिक्त ArgumentMatcher का उपयोग मॉकिंग में भी किया जा सकता है। दोनों उपयोग-मामले Mockito.argThat()
विधि का उपयोग करते हैं जो एक उचित पठनीय परीक्षण कोड प्रदान करता है।
verify(someMock).someMethod(Mockito.argThat(new ArgumentMatcher<String>() {
@Override
public boolean matches(Object o) {
return o instanceof String && !((String)o).isEmpty();
}
});
ArgumentMatcher के JavaDocs से:
चेतावनी: जटिल तर्क मिलान, विशेष रूप से कस्टम तर्क मिलानकर्ताओं का उपयोग करने के साथ उचित रहें, क्योंकि यह परीक्षण को कम पठनीय बना सकता है। कभी-कभी मॉक करने के लिए पारित होने वाले तर्कों के लिए समान () को लागू करना बेहतर होता है (मॉकिटो स्वाभाविक रूप से तर्क के लिए बराबरी का उपयोग करता है (तर्क मिलान के लिए)। इससे टेस्ट क्लीनर बन सकता है।
मॉकिटो द्वारा नकली वस्तुओं का निर्माण करें
मॉकिटो द्वारा नकली वस्तु बनाने के दो तरीके हैं:
- एनोटेशन के जरिए
- मॉक फंक्शन के जरिए
एनोटेशन:
JUnit टेस्ट रनर के साथ:
@RunWith(MockitoJUnitRunner.class)
public class FooTest {
@Mock
private Bar barMock;
// ...
}
तुम भी Mockito के JUnit उपयोग कर सकते हैं @Rule
है, जो के रूप में ही सुविधा प्रदान करता है MockitoJUnitRunner
, लेकिन एक की जरूरत नहीं है @RunWith
परीक्षण धावक:
public class FooTest {
@Rule
public MockitoRule mockito = MockitoJUnit.rule();
@Mock
private Bar barMock;
// ...
}
यदि आप @RunWith
या @Rule
एनोटेशन का उपयोग नहीं कर सकते हैं, तो आप "प्रति हाथ" @Rule
को भी @Rule
सकते हैं:
public class FooTest {
@Mock
private Bar barMock;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
// ...
}
नकली समारोह:
public class FooTest {
private Bar barMock = Mockito.mock(Bar.class);
// ...
}
प्रकार के क्षरण के कारण, आप ऊपर के रूप में एक सामान्य वर्ग का मजाक नहीं उड़ा सकते। आपको बेस क्लास का मज़ाक उड़ाना चाहिए और स्पष्ट रूप से सही जेनेरिक प्रकार कास्ट करना होगा:
public class FooTest {
private Bar<String> genericBarMock = (Bar<String>) Mockito.mock(Bar.class);
// ...
}
नकली वस्तु में व्यवहार जोड़ें
Mockito.when(mock.returnSomething()).thenReturn("my val");
mock.returnSomething(); // returns "my val"
mock.returnSomething(); // returns "my val" again
mock.returnSomething(); // returns "my val" again and again and again...
यदि आप दूसरी कॉल पर अलग मूल्य चाहते हैं तो आप तत्कालीन रिटर्न विधि में वांछित रिटर्न तर्क जोड़ सकते हैं:
Mockito.when(mock.returnSomething()).thenReturn("my val", "other val");
mock.returnSomething(); // returns "my val"
mock.returnSomething(); // returns "other val"
mock.returnSomething(); // returns "other val" again
यदि आप पद्धति को बिना व्यवहार के जोड़ देंगे तो यह शून्य हो जाएगी।
barMock.mock.returnSomethingElse(); // returns null
इस मामले में कि नकली विधि में पैरामीटर हैं, आपको मान भी घोषित करना चाहिए:
Mockito.when(mock.returnSomething("param 1")).thenReturn("my val 1");
Mockito.when(mock.returnSomething("param 2")).thenReturn("my val 2");
mock.returnSomething("param 1"); // returns "my val 1"
mock.returnSomething("param 2"); // returns "my val 2"
mock.returnSomething("param 3"); // returns null
यदि आप परम मूल्य के बारे में परवाह नहीं करते हैं तो आप Matchers.any () का उपयोग कर सकते हैं:
Mockito.when(mock.returnSomething(Matchers.any())).thenReturn("p1");
mock.returnSomething("param 1"); // returns "p1"
mock.returnSomething("param other"); // returns "p1"
अपवाद का उपयोग करने के लिए तब फेंक विधि:
Mockito.when(mock.returnSomething()).thenThrow(new Exception());
mock.returnSomething(); // throws Exception
मॉक पास करने के लिए तर्कों की जाँच करें
मान लें कि हमारे पास यह वर्ग है और हम doSmth
विधि का परीक्षण करना चाहते हैं। इस मामले में हम यह देखना चाहते हैं कि क्या पैरामीटर "वैल" foo
लिए पारित किया गया है। ऑब्जेक्ट foo
का मजाक उड़ाया जाता है।
public class Bar {
private final Foo foo;
public Bar(final Foo foo) {
this.foo = foo;
}
public void doSmth() {
foo.bla("val");
}
}
हम इसे ArgumentCaptor
साथ प्राप्त कर सकते हैं:
@Mock
private Foo fooMock;
@InjectMocks
private Bar underTest;
@Captor
private ArgumentCaptor<String> stringCaptor;
@Test
public void should_test_smth() {
underTest.doSmth();
Mockito.verify(fooMock).bla(stringCaptor.capture());
assertThat(stringCaptor.getValue(), is("val"));
}
नकली वस्तु पर विधि कॉल सत्यापित करें
यह जांचने के लिए कि क्या विधि को किसी Mockito.verify
वस्तु पर बुलाया गया है, आप Mockito.verify
उपयोग कर सकते हैं। विधि का उपयोग करें:
Mockito.verify(someMock).bla();
इस उदाहरण में, हम दावा करते हैं कि विधि bla
को someMock
मॉक ऑब्जेक्ट पर बुलाया गया था।
आप यह भी देख सकते हैं कि क्या कोई विधि कुछ मापदंडों के साथ बुलाई गई थी:
Mockito.verify(someMock).bla("param 1");
यदि आप जांचना चाहते हैं कि कोई विधि नहीं बुलाई गई थी, तो आप verify
करने के verify
एक अतिरिक्त VerificationMode
पारित कर सकते हैं:
Mockito.verify(someMock, Mockito.times(0)).bla();
यह भी काम करता है यदि आप यह जांचना चाहते हैं कि इस विधि को एक से अधिक बार कहा गया था (इस मामले में हम जाँचते हैं कि विधि bla
23% कहलाती है):
Mockito.verify(someMock, Mockito.times(23)).bla();
VerificationMode
विधि के लिए ये अधिक उदाहरण हैं, विधि को बुलाए जाने की संख्या पर अधिक नियंत्रण प्रदान करना चाहिए:
Mockito.verify(someMock, Mockito.never()).bla(); // same as Mockito.times(0)
Mockito.verify(someMock, Mockito.atLeast(3)).bla(); // min 3 calls
Mockito.verify(someMock, Mockito.atLeastOnce()).bla(); // same as Mockito.atLeast(1)
Mockito.verify(someMock, Mockito.atMost(3)).bla(); // max 3 calls
शून्य तरीकों को ठोकर मारना
void
तरीकों को doThrow () , doAnswer () , doNothing () , doCallRealMethod () तरीकों के परिवार का उपयोग करके स्टब किया जा सकता है।
Runnable mock = mock(Runnable.class);
doThrow(new UnsupportedOperationException()).when(mock).run();
mock.run(); // throws the UnsupportedOperationException
ध्यान दें कि void
तरीकों का उपयोग कर टोंटदार नहीं किया जा सकता when(..)
संकलक कारण पसंद नहीं void
तर्क के रूप में तरीकों।