2013-02-12 17 views
17

मेरे वसंत संदर्भ में कई बीन्स हैं जिनके पास राज्य है, इसलिए मैं इकाई परीक्षण से पहले/बाद में उस स्थिति को रीसेट करना चाहता हूं।मैं वसंत से तत्काल बीन्स की सूची कैसे प्राप्त कर सकता हूं?

मेरा विचार एक सहायक वर्ग में एक विधि जोड़ना था जो बस वसंत संदर्भ में सभी बीन्स के माध्यम से जाता है, @Before या @After के साथ एनोटेटेड विधियों के लिए जांच करता है और उन्हें आमंत्रित करता है।

से तत्काल बीन्स की सूची कैसे प्राप्त करें?

नोट: समाधान जो सभी परिभाषित सेमों पर बस फिर से फैलते हैं वे बेकार हैं क्योंकि मेरे पास बहुत आलसी बीन्स हैं और उनमें से कुछ को तत्काल नहीं किया जाना चाहिए क्योंकि यह कुछ परीक्षणों के लिए असफल हो जाएगा (यानी मेरे पास एक बीन्स है जिसे java.sql.DataSource की आवश्यकता है लेकिन परीक्षण काम करें क्योंकि उन्हें उस बीन की आवश्यकता नहीं है)।

+1

शायद परिभाषित "के बाद" pointcut http://static.springsource.org/spring/docs/3.0.x/reference/aop.html –

+0

आपके यूनिट टेस्ट में @DirtiesContext एनोटेशन आप जो चाहते हैं वह नहीं करता है? –

+0

@ निकोलसमोमार्ट्स: नहीं। कुछ बीन्स रीसेट करना पूरे संदर्भ को फिर से खरोंच से बनाने से बहुत सस्ता होगा। –

उत्तर

21

उदाहरण के लिए:

public static List<Object> getInstantiatedSigletons(ApplicationContext ctx) { 
      List<Object> singletons = new ArrayList<Object>(); 

      String[] all = ctx.getBeanDefinitionNames(); 

      ConfigurableListableBeanFactory clbf = ((AbstractApplicationContext) ctx).getBeanFactory(); 
      for (String name : all) { 
       Object s = clbf.getSingleton(name); 
       if (s != null) 
        singletons.add(s); 
      } 

      return singletons; 

    } 
+0

'getSingleton()' मेरे लिए पूरी तरह से काम करता है। मेरी जिंदगी अपडेट की गई (मेरा अपना जवाब देखें) –

+0

@AaronDigulla मैं 'स्प्रिंग-वेबएमवीसी' के साथ काम कर रहा हूं। मैं अपने 'डिस्पैचर सर्वर' के लिए 'WebAplicationContext' तक पहुंच कैसे प्राप्त कर सकता हूं? इसके बिना, मैं instanciated सेम पुनरावृत्त नहीं कर सकता। – smwikipedia

+1

@AaronDigulla मैंने इसे हल किया। मैं 'ApplicationContextAware' इंटरफ़ेस का उपयोग कर सकता हूं। रेफरी: http://stackoverflow.com/questions/9602664/print-all-the-pring-beans-that-are-loaded – smwikipedia

3

मुझे यकीन नहीं है कि यह आपकी मदद करेगा या नहीं।

आपको अपनी खुद की एनोटेशन बनाने की आवश्यकता है। MyAnnot। और उस कक्षा पर उस एनोटेशन को रखें जिसे आप प्राप्त करना चाहते हैं। और फिर निम्न कोड का उपयोग करके आप तत्काल बीन प्राप्त कर सकते हैं।

ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); 
scanner.addIncludeFilter(new AnnotationTypeFilter(MyAnnot.class)); 
for (BeanDefinition beanDefinition : scanner.findCandidateComponents("com.xxx.yyy")){ 
    System.out.println(beanDefinition.getBeanClassName()); 
} 

इस तरह आप अपने कस्टम एनोटेशन वाले सभी बीन्स प्राप्त कर सकते हैं।

0

मैं एक gist ApplicationContextAwareTestBase बना लिया है।

  1. यह सब आंतरिक क्षेत्रों सेट शून्य पर:

    यह सहायक वर्ग दो काम करता है। यह जावा को स्मृति मुक्त करने की अनुमति देता है जिसका अब उपयोग नहीं किया जाता है। वसंत के साथ यह कम उपयोगी है (हालांकि वसंत संदर्भ अभी भी सभी सेम के संदर्भ रखता है), हालांकि।

  2. यह संदर्भ में सभी बीन्स में @After के साथ एनोटेटेड सभी विधियों को खोजने का प्रयास करता है और परीक्षण के बाद उन्हें आमंत्रित करता है।

इस तरह, आप संदर्भ को नष्ट/ताज़ा किए बिना आसानी से अपने सिंगलेट/मैक्स की स्थिति को रीसेट कर सकते हैं।

उदाहरण:

public void MockDao implements IDao { 

    private Map<Long, Foo> database = Maps.newHashMap(); 

    @Override 
    public Foo byId(Long id) { return database.get(id)); 

    @Override 
    public void save(Foo foo) { database.put(foo.getId(), foo); } 

    @After 
    public void reset() { database.clear(); } 
} 

एनोटेशन यकीन reset() आंतरिक स्थिति को साफ करने के प्रत्येक इकाई परीक्षण के बाद बुलाया जाएगा कर देगा: आप एक नकली डीएओ की है।

3

मैं इसे बेहतर बनाने के लिए किया था एक छोटे से

@Resource 
AbstractApplicationContext context; 

@After 
public void cleanup() { 
    resetAllMocks(); 
} 

private void resetAllMocks() { 
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); 
    for (String name : context.getBeanDefinitionNames()) { 
     Object bean = beanFactory.getSingleton(name); 
     if (Mockito.mockingDetails(bean).isMock()) { 
      Mockito.reset(bean); 
     } 
    } 
} 
0

पिछले जवाब का उपयोग करना, मैं इस जावा 8 स्ट्रीम एपीआई का उपयोग करने को नवीनीकृत किया है:

@Inject 
private ApplicationContext applicationContext; 

@Before 
public void resetMocks() { 
    ConfigurableListableBeanFactory beanFactory = ((AbstractApplicationContext) applicationContext).getBeanFactory(); 
    Stream.of(applicationContext.getBeanDefinitionNames()) 
      .map(n -> beanFactory.getSingleton(n)) 
      // My ConfigurableListableBeanFactory isn't compiled for 1.8 so can't use method reference. If yours is, you can say 
      // .map(ConfigurableListableBeanFactory::getSingleton) 
      .filter(b -> Mockito.mockingDetails(b).isMock()) 
      .forEach(Mockito::reset); 
} 
संबंधित मुद्दे