java - मॉकिटो, जुनीट और स्प्रिंग




spring unit-testing (5)

आपका प्रश्न यह पूछता है कि आपने जो तीन उदाहरण दिए हैं, वह पसंदीदा दृष्टिकोण है।

प्रतिबिंब परीक्षण का उपयोग कर उदाहरण 1 यूनिट परीक्षण के लिए एक अच्छा दृष्टिकोण नहीं है। आप वास्तव में यूनिट परीक्षण के लिए वसंत संदर्भ लोड नहीं करना चाहते हैं। बस अपने अन्य उदाहरणों के अनुसार दिखाए गए अनुसार नकल करें और इंजेक्ट करें।

यदि आप कुछ एकीकरण परीक्षण करना चाहते हैं, तो आप वसंत संदर्भ लोड करना चाहते हैं, हालांकि मैं @RunWith(SpringJUnit4ClassRunner.class) का उपयोग @RunWith(SpringJUnit4ClassRunner.class) के साथ संदर्भ लोड करने के लिए करना @Autowired यदि आपको स्पष्ट रूप से 'बीन्स' तक पहुंच की आवश्यकता है।

उदाहरण 2 एक वैध दृष्टिकोण है और @RunWith(MockitoJUnitRunner.class) का उपयोग @Before विधि निर्दिष्ट करने और MockitoAnnotations.initMocks(this); को एक स्पष्ट कॉल निर्दिष्ट करने की आवश्यकता को हटा देगा MockitoAnnotations.initMocks(this);

उदाहरण 3 एक और मान्य दृष्टिकोण है जो @RunWith(...) उपयोग नहीं करता है। आपने स्पष्ट रूप से परीक्षण HelloFacadeImpl तहत अपनी कक्षा को HelloFacadeImpl चालू नहीं किया है, लेकिन आप उदाहरण 2 के साथ ऐसा ही कर सकते थे।

मेरा सुझाव है कि आप अपने यूनिट परीक्षण के लिए उदाहरण 2 का उपयोग करें क्योंकि यह कोड अव्यवस्था को कम करता है। यदि आप ऐसा करने के लिए मजबूर होते हैं तो आप अधिक वर्बोज़ कॉन्फ़िगरेशन पर वापस आ सकते हैं।

मैंने आज केवल मॉकिटो के बारे में जानना शुरू कर दिया। मैंने कुछ सरल परीक्षण लिखा (जुनीट के साथ, नीचे देखें), लेकिन मैं यह नहीं समझ सकता कि मैं स्प्रिंग के मैनेज बीन्स के अंदर नकली वस्तु का उपयोग कैसे कर सकता हूं। वसंत के साथ काम करने के लिए सबसे अच्छा अभ्यास क्या है। मुझे अपने बीन के लिए नकली निर्भरता कैसे इंजेक्ट करनी चाहिए?

आप इसे मेरे प्रश्न पर वापस छोड़ सकते हैं।

सबसे पहले, मैंने जो सीखा है। यह बहुत अच्छा लेख है मॉक्स स्टब्स नहीं हैं जो मूल बातें बताते हैं (मॉक के चेक व्यवहार सत्यापन राज्य सत्यापन नहीं)। फिर यहां एक अच्छा उदाहरण है मॉकिटो यहाँ मॉकिटो के साथ मजाक कर रहा है, हमारे पास स्पष्टीकरण है कि मॉकिटो की नकली वस्तुएं दोनों नकली और स्टब्स हैं

यहां Matchers और यहां Matchers आप अधिक उदाहरण पा सकते हैं।

इस प्रयोग

@Test
public void testReal(){
    List<String> mockedList = mock(List.class);
     //stubbing
     //when(mockedList.get(0)).thenReturn("first");

    mockedList.get(anyInt());
    OngoingStubbing<String> stub= when(null);
    stub.thenReturn("first");

    //String res = mockedList.get(0);
                //System.out.println(res);

     //you can also verify using argument matcher
     //verify(mockedList).get(anyInt());

    verify(mockedList);
    mockedList.get(anyInt());
}

बस ठीक काम करता है।

मेरे प्रश्न पर वापस। यहां स्प्रिंग बीन में मॉकिटो मोक्स इंजेक्शन करने से कोई स्प्रिंग ReflectionTestUtils.setField() का उपयोग करने की कोशिश करता है, लेकिन यहां से वसंत एकीकरण टेस्ट, मॉक ऑब्जेक्ट्स बनाने से हमारे पास स्प्रिंग के संदर्भ को बदलने की सिफारिश है।

मैं वास्तव में पिछले दो लिंक नहीं समझ पाया ... क्या कोई मुझे बता सकता है कि स्प्रिंग में मॉकिटो के साथ क्या समस्या है? इस समाधान के साथ क्या गलत है?

@InjectMocks
private MyTestObject testObject

@Mock
private MyDependentObject mockedObject

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

https://stackoverflow.com/a/8742745/1137529

संपादित करें : मैं वास्तव में स्पष्ट नहीं था। मैं अपने स्वयं को स्पष्ट करने के लिए कोड के 3 उदाहरण प्रदान करूंगा: मान लीजिए, हमारे पास विधि printHello() साथ बीन हैलोवर्ल्ड है और विधि के साथ बीन हैलोफाकडे sayHello की विधि printHello() को कॉल अग्रेषित करें।

पहला उदाहरण निर्भरता इंजेक्शन (डीआई) के लिए ReflectionTestUtils का उपयोग करके स्प्रिंग के संदर्भ और कस्टम धावक के बिना उपयोग कर रहा है:

public class Hello1Test  {
private ApplicationContext ctx;

@Before
public void setUp() {
    MockitoAnnotations.initMocks(this);
    this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}



@Test
public void testHelloFacade() {
    HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
    HelloWorld mock = mock(HelloWorld.class);
    doNothing().when(mock).printHello();

    ReflectionTestUtils.setField(obj, "hello", mock);
    obj.sayHello();

    verify(mock, times(1)).printHello();
}

}

जैसा कि @Noam ने MockitoAnnotations.initMocks(this); को स्पष्ट कॉल के MockitoAnnotations.initMocks(this); चलाने के तरीके को इंगित किया MockitoAnnotations.initMocks(this); । मैं इस उदाहरण पर वसंत के संदर्भ का उपयोग भी छोड़ दूंगा।

@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {


@InjectMocks
private HelloFacade obj =  new HelloFacadeImpl();

@Mock
private HelloWorld mock;


@Test
public void testHelloFacade() {
    doNothing().when(mock).printHello();
    obj.sayHello();
}

}

ऐसा करने का एक और तरीका

public class Hello1aTest {

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


@InjectMocks
private HelloFacadeImpl obj;

@Mock
private HelloWorld mock;


@Test
public void testHelloFacade() {
    doNothing().when(mock).printHello();
    obj.sayHello();
}

}

नोथ, कि प्रत्याशित उदाहरण में हमें हैलोफैक्डइम्पल को मैन्युअल रूप से निकालना है और इसे हैलोफाकैड को असाइन करना है, बेक्यूज हैलोफाक इंटरफ़ेस है। आखिरी उदाहरण में, हम सिर्फ HelloFacadeImpl घोषित कर सकते हैं और मोकिटो हमारे लिए इसे तुरंत चालू कर देगा। इस दृष्टिकोण की कमी अब, यूनिट-अंडर-टेस्ट इंप-क्लास है और इंटरफ़ेस नहीं है।


आपको वास्तव में MockitoAnnotations.initMocks(this); आवश्यकता नहीं है MockitoAnnotations.initMocks(this); यदि आप मॉकिटो 1.9 (या नए) का उपयोग कर रहे हैं - आपको बस यह चाहिए:

@InjectMocks
private MyTestObject testObject;

@Mock
private MyDependentObject mockedObject;

@InjectMocks एनोटेशन MyTestObject ऑब्जेक्ट पर आपके सभी @InjectMocks इंजेक्ट करेगा।


मेरा संक्षिप्त सारांश यहाँ है।

यदि आप एक यूनिट टेस्ट लिखना चाहते हैं, तो स्प्रिंग एप्लिकेशन कॉन्टेक्स्ट का उपयोग न करें क्योंकि आप नहीं चाहते हैं कि कक्षा में इंजेक्शन वाली वास्तविक निर्भरताएं आप इकाई परीक्षण कर रहे हों। बजाय, वर्ग के शीर्ष पर @RunWith(MockitoJUnitRunner.class) एनोटेशन के साथ या @Before विधि में MockitoAnnotations.initMocks(this) साथ, या तो mocks का उपयोग करें।

यदि आप एकीकरण परीक्षण लिखना चाहते हैं, तो इसका उपयोग करें:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("yourTestApplicationContext.xml")

उदाहरण के लिए इन-मेमोरी डेटाबेस के साथ अपना एप्लिकेशन संदर्भ सेट अप करने के लिए। आम तौर पर आप एकीकरण परीक्षणों में MockitoAnnotations.initMocks(this) का उपयोग नहीं करते हैं, लेकिन आप ऊपर वर्णित MockitoAnnotations.initMocks(this) दृष्टिकोण का उपयोग कर ऐसा कर सकते हैं।


यदि आप अपनी परियोजना को स्प्रिंग बूट 1.4 में माइग्रेट करेंगे, तो आप @MockBean को @MockBean लिए नई एनोटेशन @MockBean उपयोग कर सकते हैं। उस सुविधा के साथ आप अपने परीक्षण से @InjectMocks के @Mock और @InjectMocks एनोटेशन को हटा सकते हैं।


स्प्रिंग 4.2 में कुछ नई परीक्षण सुविधाओं का परिचय। आरसी 1 एक स्प्रिंग एकीकरण परीक्षण SpringJUnit4ClassRunner जो SpringJUnit4ClassRunner पर भरोसा नहीं SpringJUnit4ClassRunner । दस्तावेज के this भाग को देखें।

आपके मामले में आप अपने वसंत एकीकरण परीक्षण लिख सकते हैं और अभी भी इस तरह के मोजे का उपयोग कर सकते हैं:

@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration("test-app-ctx.xml")
public class FooTest {

    @ClassRule
    public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();

    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();

    @Autowired
    @InjectMocks
    TestTarget sut;

    @Mock
    Foo mockFoo;

    @Test
    public void someTest() {
         // ....
    }
}




mockito