2010-11-09 11 views
5

मैं एक मुद्दा है कि केवल वसंत के आईओसी कंटेनर सुविधाओं और संदर्भ सेटअप की समझ की मेरी मौलिक कमी के साथ समझाया जा सकता है में भाग है, इसलिए मैं इस बारे में स्पष्टीकरण के लिए पूछना होगा।स्प्रिंग JUnit4 मैनुअल/ऑटो तारों दुविधा

  • जावा 1.6
  • वसंत 2.5.6
  • RichFaces 3.3.1-जीए यूआई
  • स्प्रिंग ढांचे:

    बस संदर्भ के लिए

    , एक आवेदन मैं maintaing हूँ प्रौद्योगिकियों के निम्नलिखित ढेर है डीएओ समर्थन

  • मेवेन का निर्माण प्रबंधक के रूप में उपयोग किया जाता है
  • JUnit 4.4 कोई नहीं है स्प्रिंग जेडीबीसी मॉड्यूल के लिए बीन प्रबंधन के लिए बीन प्रबंधन के लिए प्रयोग किया जाता है डब्ल्यू परीक्षण इंजन

के रूप में पेश मैं पूर्वव्यापी प्रभाव से (sic!) लेखन JUnit आवेदन के लिए परीक्षण और क्या आश्चर्य मैं हूँ कि मैं का सहारा के बिना सेटर इंजेक्शन का उपयोग करके एक परीक्षण वर्ग में एक सेम इंजेक्षन करने में सक्षम नहीं था हूँ @Autowire नोटेशन।

मुझे एक उदाहरण स्थापित करने और कॉन्फ़िगरेशन फ़ाइलों के साथ प्रदान करने दें।

परीक्षण वर्ग TypeTest वास्तव में सरल है:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class TypeTest { 

    @Autowired 
    private IType type; 

    @Test 
    public void testFindAllTypes() { 
     List<Type> result; 

     try { 
      result = type.findAlltTypes(); 
      assertNotNull(result); 
     } catch (Exception e) { 
      e.printStackTrace(); 
      fail("Exception caught with " + e.getMessage()); 
     } 
    } 
} 

इसका संदर्भ TestStackOverflowExample-context.xml में परिभाषित किया गया है:

<context:property-placeholder location="classpath:testContext.properties" /> 
<context:annotation-config /> 
<tx:annotation-driven /> 

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
    destroy-method="close"> 
    <property name="driverClassName" value="${db.connection.driver.class}" /> 
    <property name="url" value="${db.connection.url}" /> 
    <property name="username" value="${db.connection.username}" /> 
    <property name="password" value="${db.connection.password}" /> 
</bean> 

<bean id="transactionManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 

<bean id="beanDAO" class="com.example.BeanDAOImpl"> 
    <property name="ds" ref="dataSource"></property> 
    <property name="beanDAOTwo" ref="beanDAOTwo"></property> 
</bean> 

<bean id="beanDAOTwo" class="com.example.BeanDAOTwoImpl"> 
    <property name="ds" ref="dataSource"></property> 
</bean> 

<bean id="type" class="com.example.TypeImpl"> 
    <property name="beanDAO" ref="beanDAO"></property> 
</bean> 

TestContext.properties classpath में है और पर होता है डेटा स्रोत के लिए आवश्यक ly db-विशिष्ट डेटा।

यह एक आकर्षण की तरह काम करता है, लेकिन मेरे सवाल है - यह क्यों काम नहीं करता है जब मैं करने के लिए मैन्युअल रूप से तार सेम कोशिश करते हैं और के रूप में सेटर इंजेक्शन करते हैं: मैं यहाँ क्या याद आ रही है

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class TypeTest { 

    private IType type; 

    public IType getType() { 
     return type; 
    } 

    public void setType(IType type) { 
     this.type= type; 
    } 

    @Test 
    public void testFindAllTypes(){ 
    //snip, snip... 
    } 
} 

? कॉन्फ़िगरेशन का कौन सा हिस्सा गलत है? जब मैं मैन्युअल setters के माध्यम से सेम इंजेक्षन करने की कोशिश, परीक्षण विफल रहता है क्योंकि इस भाग

result = type.findAlltTypes(); 

क्रम में अशक्त के रूप में हल हो गई है। मैंने, निश्चित रूप से, वसंत संदर्भ मैनुअल से परामर्श किया है और एक्सएमएल विन्यास के विभिन्न संयोजनों की कोशिश की है; मैं यह निष्कर्ष निकाल सकता हूं कि वसंत बीन्स इंजेक्ट करने में असमर्थ था क्योंकि यह किसी भी तरह से स्प्रिंग टेस्ट संदर्भ संदर्भ को ठीक से अपरिवर्तित करने में विफल रहता है लेकिन @Autowired का उपयोग करके यह "स्वचालित रूप से" होता है और मैं वास्तव में नहीं देख सकता कि ऐसा क्यों है क्योंकि Autowired दोनों का जावाडॉक एनोटेशन और इसकी PostProcessor कक्षा का उल्लेख नहीं है।

इसके अलावा जोड़ने के लायक तथ्य यह है कि @Autowired केवल यहां आवेदन में इस्तेमाल किया जाता है। कहीं और केवल मैनुअल तारों किया जाता है, तो यह भी सवाल आगे लाता है - अपने परीक्षण में यह क्यों, वहाँ और नहीं यहाँ काम कर रहा है? मुझे डीआई कॉन्फ़िगरेशन का क्या हिस्सा याद आ रहा है? @Autowired कैसे वसंत संदर्भ का संदर्भ प्राप्त करता है?

संपादित करें: मैं भी इस की कोशिश की है, लेकिन एक ही परिणाम के साथ:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class TypeTest implements ApplicationContextAware{ 

    private IType type; 

    private ApplicationContext ctx; 

    public TypeTest(){ 
       super(); 
       ctx = new FileSystemXmlApplicationContext("/TypeTest-context.xml"); 
       ctx.getBean("type"); 
    } 

    public IType getType() { 
     return type; 
    } 

    public void setType(IType type) { 
     this.type= type; 
    } 

    @Test 
    public void testFindAllTypes(){ 
    //snip, snip... 
    } 
} 

किसी भी अन्य विचारों, शायद?

EDIT2: मुझे अपने TestContextListener या BeanPostProcessor लिखने के बिना एक रास्ता मिला है। यह हैरत की बात है सरल है और यह पता चला है कि मैं अपने पिछले संपादन के साथ सही रास्ते पर था:

1) निर्माता आधारित संदर्भ के समाधान:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class TypeTest{ 

    private IType type; 

    private ApplicationContext ctx; 

    public TypeTest(){ 
     super(); 
     ctx = new FileSystemXmlApplicationContext("/TypeTest-context.xml"); 
     type = ctx.getBean("type"); 
    } 

    public IType getType() { 
     return type; 
    } 

    public void setType(IType type) { 
     this.type= type; 
    } 

    @Test 
    public void testFindAllTypes(){ 
    //snip, snip... 
    } 
} 

2) को लागू करने ApplicationContextAware इंटरफ़ेस द्वारा:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
public class TypeTest implements ApplicationContextAware{ 

    private IType type; 
    private ApplicationContext ctx; 

    public IType getType() { 
     return type; 
    } 

    public void setType(IType type) { 
     this.type= type; 
    } 

@Override 
    public void setApplicationContext(ApplicationContext ctx) throws BeansException { 
    this.ctx = ctx; 
    type = (Type) ctx.getBean("type"); 
} 

    @Test 
    public void testFindAllTypes(){ 
    //snip, snip... 
    } 
} 

इनमें से दोनों दृष्टिकोण ठीक ढंग से स्थापित बीन्स हैं।

उत्तर

5

आप org.springframework.test.context.support.DependencyInjectionTestExecutionListener के स्रोत पर एक नज़र डालें, तो आप निम्नलिखित विधि (प्रारूपित और स्पष्टता के लिए टिप्पणी की) देखेंगे:

protected void injectDependencies(final TestContext testContext) 
throws Exception { 
    Object bean = testContext.getTestInstance(); 
    AutowireCapableBeanFactory beanFactory = testContext.getApplicationContext() 
      .getAutowireCapableBeanFactory(); 
    beanFactory.autowireBeanProperties(bean, 

      AutowireCapableBeanFactory.AUTOWIRE_NO, 
      // no autowiring!!!!!!!! 

      false 
     ); 

    beanFactory.initializeBean(bean, testContext.getTestClass().getName()); 
    // but here, bean post processors are run 

    testContext.removeAttribute(REINJECT_DEPENDENCIES_ATTRIBUTE); 
} 

तो परीक्षण वस्तु ऑटो तारों के बिना एक सेम है। हालांकि, @AutoWired, @Resource आदि, ऑटोवॉयरिंग तंत्र का उपयोग न करें, वे BeanPostProcessor का उपयोग करते हैं। और इसलिए निर्भरताओं को इंजेक्शन दिया जाता है यदि केवल और यदि टिप्पणियां उपयोग की जाती हैं (या यदि आप कुछ अन्य BeanPostProcessor पंजीकृत करते हैं)।

(ऊपर कोड स्प्रिंग 3.0.x से है, लेकिन मुझे यकीन है यह 2.5.x में एक ही था)

+0

+1, अच्छा खोजने .. – Bozho

+0

तो हम समाप्त करने के लिए सुरक्षित वहाँ प्रभावी ढंग से करने के लिए कोई रास्ता नहीं है कर रहे हैं मैन्युअल रूप से परीक्षण बीन्स तार? यदि संभव हो तो मैं एनोटेशन का उपयोग करना छोड़ दूंगा। – quantum

+0

बेशक यह किया जा सकता है। वसंत में, लगभग कुछ भी किया जा सकता है। आपको अपना खुद का लिखना होगा) बीनपोस्ट प्रोसेसर या बी) टेस्टएक्सक्यूशन लिस्टनर, अपनी टेस्ट क्लास के लिए बीन की खोज करें और ऑटोवायर कैपेबलबीन फैक्ट्री का उपयोग करके इसे तार दें। –

संबंधित मुद्दे