2012-03-21 11 views
25

मैं एक कक्षा के लिए यूनिट टेस्ट लिखने की कोशिश कर रहा हूं जिसमें इसके कई फ़ील्ड @Autowired चिह्नित हैं। इस तथ्य को देखते हुए कि वसंत स्वचालित रूप से इन क्षेत्रों के लिए ठोस कार्यान्वयन को हल कर रहा है, मुझे परीक्षण करने के दौरान निर्भरता के रूप में मेरी मॉक ऑब्जेक्ट्स (EasyMock के माध्यम से बनाई गई) को प्लग करने का एक कठिन समय लग रहा है। कक्षा में @Autowired का उपयोग करना उस वर्ग में सेटर्स की कमी का मतलब है। कक्षा में अतिरिक्त सेटर्स बनाने के बिना मेरे नकली वस्तुओं को प्लग करने का कोई तरीका है?यूनिट जूनिट और इज़ीमॉक का उपयोग कर ऑटोवायर नोटेशन के साथ एक कक्षा का परीक्षण?

public class SomeClassUnderTest implements SomeOtherClass{ 

@Autowired 
private SomeType someType; 

@Autowired 
private SomeOtherType someOtherType; 

@Override 
public SomeReturnType someMethodIWouldLikeToTest(){ 
//Uses someType and someOtherType and returns SomeReturnType 
} 

} 

यहाँ है कैसे मैं अपने टेस्ट वर्ग क्राफ्टिंग हूँ इससे पहले कि मैं दीवार से टकरा:

public class MyTestClassForSomeClassUnderTest{ 
    private SomeType someType; 
    private SomeOtherType someOtherType; 

    @Before 
    public void testSetUp(){ 
    SomeClassUnderTest someClassToTest = new SomeClassUnderTest(); 
    someType = EasyMock.createMock(SomeType.class); 
    someOtherType = EasyMock.createMock(SomeOtherType.class); 
    //How to set dependencies???? 
    } 

    @Test 
    public void TestSomeMethodIWouldLikeToTest(){ 
    //?????? 
    } 

} 

यह एक पाने के लिए बहुत अच्छा होगा

यहाँ मैं क्या हासिल करने की कोशिश कर रहा हूँ का एक उदाहरण है सही दिशा में धक्का।

धन्यवाद

उत्तर

34

आप संजीदगी से ReflectionTestUtils उदा का उपयोग कर, सीधे फील्ड में निर्भरता इंजेक्षन कर सकते हैं

ReflectionTestUtils.setField(testInstance, "fieldName", fieldValue); 

कुछ तर्क था कि यह वैसे भी वर्ग के लिए एक पैकेज दृश्य सेटर विधि जोड़ने को प्राथमिकता दी जाती, परीक्षण के द्वारा ही किया करते थे। वैकल्पिक रूप से, ऑटोवायर किए गए फ़ील्ड की बजाय ऑटोवायर कन्स्ट्रक्टर का उपयोग करें, और उसमें परीक्षण निर्भरताओं को इंजेक्ट करें।

+0

टिप के लिए धन्यवाद। –

+1

http://stackoverflow.com/questions/16426323/injecting-into-autowired-variable-during-testing – Dan

+0

EasyMock mock इंजेक्शन के लिए Mockito को संस्करण 3.2 समान एनोटेशन के बाद से समर्थन करता है। मेरा जवाब देखें – krm

6

हालांकि इन क्षेत्रों को प्रतिबिंब के माध्यम से सेट करना संभव है, ऐसा करने से आपके विकास उपकरण इन क्षेत्रों के उपयोग को ढूंढने से रोक देंगे, और भविष्य में SomeClassToTest को दोबारा प्रतिक्रिया देना आपके लिए कठिन होगा।

इन क्षेत्रों के लिए सार्वजनिक सेटर्स जोड़ना बेहतर होगा, और इसके बजाय @Autowired एनोटेशन रखें। यह न केवल प्रतिबिंब से बचता है, बल्कि यह वर्ग के बाहरी इंटरफ़ेस को भी स्पष्ट करता है और यह सुनिश्चित करता है कि आपका यूनिट परीक्षण केवल इस इंटरफ़ेस का उपयोग करता है। मुझे लगता है कि SomeClassToTest पहले से ही SomeOtherClass इंटरफ़ेस लागू करता है, और मुझे लगता है कि SomeClassToTest के क्लाइंट केवल इस इंटरफ़ेस का उपयोग करते हैं, इसलिए SomeClassToTest पर सेटर्स बनाने में थोड़ा खतरा नहीं है।

बेहतर अभी भी, कन्स्ट्रक्टर इंजेक्शन का उपयोग करें और फ़ील्ड को अंतिम बनाएं। आप अभी भी निर्माता तर्क पर @Autowired का उपयोग कर सकते हैं।

1

मैं स्वीकार किए गए उत्तर की अनुशंसा नहीं करता हूं, यानी अपने आप पर प्रतिबिंब का उपयोग करके (एक नकली ढांचे के बिना)।

ईज़ीमोक के संस्करण 3.2 के बाद से आप मोज़े को परिभाषित करने और परीक्षण के तहत कक्षा में इंजेक्ट करने के लिए एनोटेशन का उपयोग कर सकते हैं। पूरा विवरण इसे कैसे करना EasyMock की आधिकारिक दस्तावेज में पाया जा सकता है: http://easymock.org/user-guide.html#mocking-annotations

यहाँ उपर्युक्त साइट से एक उदाहरण है:

import static org.easymock.EasyMock.*; 
import org.easymock.EasyMockRunner; 
import org.easymock.TestSubject; 
import org.easymock.Mock; 
import org.junit.Test; 
import org.junit.runner.RunWith; 

@RunWith(EasyMockRunner.class) 
public class ExampleTest { 

    @TestSubject 
    private ClassUnderTest classUnderTest = new ClassUnderTest(); // 2 

    @Mock 
    private Collaborator mock; // 1 

    @Test 
    public void testRemoveNonExistingDocument() { 
    replay(mock); 
    classUnderTest.removeDocument("Does not exist"); 
    } 
} 
संबंधित मुद्दे