2013-08-27 5 views
10

मेरे पास कुछ परीक्षण हैं जो कुछ ग़लत स्कॉप्स का गलत तरीके से उपयोग किए जाने पर मैं विफल होना चाहता हूं। उदाहरण के लिए, @Singleton में कोई @RequestScoped या @TestScoped निर्भरता नहीं होनी चाहिए (Provider<> एस ठीक है, ठीक है)।मैं परीक्षण में एक गिइस स्कोप के उपयोग को कैसे वैध कर सकता हूं?

उत्पादन में, यह आंशिक रूप से हल हो गया है क्योंकि दायरे से पहले सिंगलटन का निर्माण किया जाएगा, जिसके परिणामस्वरूप दायरे दर्ज की गई है, जिसके परिणामस्वरूप OutOfScopeException एस है। लेकिन विकास में, दायरे के अंदर सिंगलटन आलसी बनाया जाएगा, और कोई समस्या स्पष्ट नहीं है।

thesetwo खुले मुद्दों के आधार पर, ऐसा लगता है कि ऐसा करने के लिए कोई आसान, अंतर्निहित तरीका नहीं है। क्या मैं एसपीआई का उपयोग करके इसे प्राप्त कर सकता हूं? मैंने TypeListener का उपयोग करने का प्रयास किया लेकिन यह स्पष्ट नहीं है कि किसी दिए गए प्रकार की निर्भरताओं को कैसे प्राप्त किया जाए।

उत्तर

1

यहाँ कैसे मैंने बार आरामदेह और चिंतामुक्त है ProvisionListener का उपयोग करके, Guice के 4.0 बीटा के साथ इसे लगाया। मैंने TypeListener की कोशिश की लेकिन ऐसा लगता है कि TypeListener एस को गुइसे से पहले कहा जाता है कि उस प्रकार की निर्भरताओं के लिए जरूरी है। इससे एक मामले में अपवाद और यहां तक ​​कि एक डेडलॉक भी हुआ।

private static class ScopeValidator implements ProvisionListener { 
    private @Inject Injector injector; 
    private @Inject WhateverScope scope; 

    @Override 
    public <T> void onProvision(ProvisionInvocation<T> provision) { 
     if (injector == null) { 
      // The injector isn't created yet, just return. This isn't a 
      // problem because any scope violations will be caught by 
      // WhateverScope itself here (throwing an OutOfScopeException) 
      return; 
     } 

     Binding<?> binding = provision.getBinding(); 
     Key<?> key = binding.getKey(); 

     if (Scopes.isSingleton(binding) && binding instanceof HasDependencies) { 
      Set<Dependency<?>> dependencies = ((HasDependencies) binding).getDependencies(); 

      for (Dependency<?> dependency : dependencies) { 
       Key<?> dependencyKey = dependency.getKey(); 
       Binding<?> dependencyBinding = injector.getExistingBinding(dependencyKey); 

       if (dependencyBinding != null && Scopes.isScoped(dependencyBinding, whateverScope, WhateverScoped.class)) { 
        throw new ProvisionException(String.format(
          "Singleton %s depends on @WhateverScoped %s", 
          key, dependencyKey)); 
       } 
      } 
     } 
    } 
} 
2

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

अब के लिए एक उदाहरण है कि बाइंडिंग स्कॉप्स कैसे प्राप्त करें।

मॉड्यूल

public class ScopeTestModel extends ServletModule { 

    @Override 
    protected void configureServlets() { 
    super 
     .configureServlets(); 
    bind(Key.get(Object.class, Names.named("REQ1"))).to(Object.class).in(ServletScopes.REQUEST); 
    bind(Key.get(Object.class, Names.named("REQ2"))).to(RequestScopedObject.class); 

    bind(Key.get(Object.class, Names.named("SINGLETON1"))).to(Object.class).asEagerSingleton(); 
    bind(Key.get(Object.class, Names.named("SINGLETON2"))).to(Object.class).in(Scopes.SINGLETON); 
    bind(Key.get(Object.class, Names.named("SINGLETON3"))).to(SingletonScopedObject.class); 

    bind(Key.get(Object.class, Names.named("SESS1"))).to(Object.class).in(ServletScopes.SESSION); 
    bind(Key.get(Object.class, Names.named("SESS2"))).to(SessionScopedObject.class); 
    } 
} 

testcase

public class TestScopeBinding { 

    private Injector injector = Guice.createInjector(new ScopeTestModel()); 

    @Test 
    public void testRequestScope() throws Exception { 
    Binding<Object> req1 = injector.getBinding(Key.get(Object.class, Names.named("REQ1"))); 
    Binding<Object> req2 = injector.getBinding(Key.get(Object.class, Names.named("REQ2"))); 

    Scope scope1 = getScopeInstanceOrNull(req1); 
    Scope scope2 = getScopeInstanceOrNull(req2); 

    Assert.assertEquals(ServletScopes.REQUEST,scope1); 
    Assert.assertEquals(ServletScopes.REQUEST,scope2); 
    } 

    @Test 
    public void testSessionScope() throws Exception { 
    injector.getAllBindings(); 
    Binding<Object> sess1 = injector.getBinding(Key.get(Object.class, Names.named("SESS1"))); 
    Binding<Object> sess2 = injector.getBinding(Key.get(Object.class, Names.named("SESS2"))); 

    Scope scope1 = getScopeInstanceOrNull(sess1); 
    Scope scope2 = getScopeInstanceOrNull(sess2); 

    Assert.assertEquals(ServletScopes.SESSION,scope1); 
    Assert.assertEquals(ServletScopes.SESSION,scope2); 
    } 

    @Test 
    public void testSingletonScope() throws Exception { 
    injector.getAllBindings(); 
    Binding<Object> sng1 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON1"))); 
    Binding<Object> sng2 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON2"))); 
    Binding<Object> sng3 = injector.getBinding(Key.get(Object.class, Names.named("SINGLETON3"))); 

    Scope scope1 = getScopeInstanceOrNull(sng1); 
    Scope scope2 = getScopeInstanceOrNull(sng2); 
    Scope scope3 = getScopeInstanceOrNull(sng3); 

    Assert.assertEquals(Scopes.SINGLETON,scope1); 
    Assert.assertEquals(Scopes.SINGLETON,scope2); 
    Assert.assertEquals(Scopes.SINGLETON,scope3); 
    } 

    private Scope getScopeInstanceOrNull(final Binding<?> binding) { 
    return binding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Scope>() { 

     @Override 
     public Scope visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) { 
     throw new RuntimeException(String.format("I don't know how to handle the scopeAnnotation: %s",scopeAnnotation.getCanonicalName())); 
     } 

     @Override 
     public Scope visitNoScoping() { 
      if(binding instanceof LinkedKeyBinding) { 
      Binding<?> childBinding = injector.getBinding(((LinkedKeyBinding)binding).getLinkedKey()); 
      return getScopeInstanceOrNull(childBinding); 
      } 
     return null; 
     } 

     @Override 
     public Scope visitEagerSingleton() { 
     return Scopes.SINGLETON; 
     } 

     public Scope visitScope(Scope scope) { 
     return scope; 
     } 
    }); 
    } 
} 

Scoped वस्तुओं

@RequestScoped 
public class RequestScopedObject extends Object { 

} 

@SessionScoped 
public class SessionScopedObject extends Object { 

} 

@Singleton 
public class SingletonScopedObject extends Object { 

} 
+1

धन्यवाद, यह निश्चित रूप से पहेली का एक टुकड़ा है। यह जांचने के लिए कि बाध्यकारी एक सिंगलटन है या नहीं, वहां 'Scopes.isSingleton() 'भी है। पहेली का दूसरा भाग वह जगह है जहां मैं फंस गया था। मुझे एक गिइस 4 समाधान मिला है जिसे मैं पोस्ट करने जा रहा हूं, लेकिन यदि संभव हो तो मुझे अभी भी एक गिइस 3 समाधान पसंद आएगा। –

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