2013-02-08 9 views
5

Mam proste POJO:wstrzykiwanie nazwie Guice singleton

public class MyPOJO { 
    @Inject 
    private Fizz fizz; 

    private Buzz buzz; 

    // rest of class omitted for brevity 
} 

chciałbym skonfigurować mój moduł Guice takie, że istnieją dwa rodzaje Fizz es że wstrzykuje:

  1. Specjalny, globally-singleton Fizz instancja; i
  2. inne (nie-specjalnego) Fizz przypadki

że chce MyPOJO wstrzykiwano w specjalnej/jednoelementowy przykład. Więc mój zmodyfikowany kod:

public class MyPOJO { 
    @Inject @Named("Special-Fizz") 
    private Fizz fizz; 

    private Buzz buzz; 

    // rest of class omitted for brevity 
} 

Wtedy w moim modułu:

public class MyModule extends AbstractModule { 
    @Override 
    public void configure() { 
     bind(Fizz.class).annotatedWith(
      Names.named("Special-Fizz")) 
      .to(Fizz.class); 

     // Other bindings here... 
    } 

    @Provides @Singleton 
    private Fizz providesFizz() { 
     return new Fizz(true, "Special", 12.0); 
    } 
} 

Ale gdy próbuję testów jednostkowych (JUnit 4.10) to:

public class MyTest { 
    @Named("Special-Fizz") private Fizz specialFizz; 

    @Test 
    public void usingNamedShouldInjectSpecialFizz() { 
     MyModule mod = new MyModule(); 
     Injector injector = Guice.createInjector(mod); 

     specialFizz = injector.getInstance(Fizz.class); 

     Assert.assertTrue(specialFizz != null); 
    } 
} 

przechodzi ten. Jak na razie dobrze. Ale jeśli mogę zmienić nazwę pola specialFizz:

@Named("Special-Fuzz-This-Shouldnt-Work") private Fizz specialFizz; 

i ponownie uruchomić test, nadal przechodzi. Czemu?!? Gdzie ja tu zbłądziłem? Z góry dziękuję.

Odpowiedz

3

Bardzo dziwne. Guice powinien narzekać, jeśli nie może znaleźć wiązania, które wstrzykuje. Jestem trochę zdezorientowany twoim testem. Nie wiem, co robi injector.inject. Czy masz na myśli injectMembers? To może mieć więcej sensu, aby uzyskać instancję POJO i upewnić się, że działa zgodnie z oczekiwaniami. Może coś takiego:

public class FizzTest { 

    public static class MyModule extends AbstractModule { 
    @Override 
    protected void configure() { 
    } 

    @Provides 
    @Singleton 
    @Named("Special-Fizz") 
    public Fizz providesFizz() { 
     return new Fizz(true); 
    } 
    } 

    public static class Fizz { 
    boolean special = false; 
    public Fizz() {} 
    public Fizz(boolean special) { 
     this.special = special; 
    } 
    } 

    public static class MyPOJO { 
    @Inject @Named("Special-Fizz") 
    private Fizz fizz; 

    @Inject 
    private Fizz otherFizz; 
    } 

    @Test 
    public void test() { 
    MyModule mod = new MyModule(); 
    Injector injector = Guice.createInjector(mod); 

    MyPOJO pojo = injector.getInstance(MyPOJO.class); 
    assertTrue(pojo.fizz.special); 
    assertTrue(!pojo.otherFizz.special); 
    } 

} 
+0

Dzięki @condit (+1) - to był błąd z mojej strony przy pisaniu tego pytania. Zmieniłem moje oryginalne pytanie, aby pokazać, że w rzeczywistości nazywam 'injector.getInstance', a nie' injector.inject'. Czy to coś dla ciebie zmieni? Czy 'getInstance' nie jest dla mnie poprawny? Jeśli tak, dlaczego i czym jest? Dzięki jeszcze raz! – IAmYourFaja

+0

W teście pytasz wtryskiwacz o instancję 'Fizz', która zawsze będzie w stanie Ci zapewnić (z powodu twojej metody" @ Provides "). Myślę, że zamiast tego chcesz utworzyć instancję 'MyPOJO'. Zauważ, że 'Fizz', który otrzymujesz, nie ma związku z testem członka Fizz. Zatem zmiana '@Named' nie będzie miała żadnego wpływu w tym przypadku. – condit

+0

Przybiłeś to. Poprosiłem go tylko o wstrzyknięcie "MyPOJO" i poprawnie wstrzyknęło mu własność 'Fizz' z moim specjalnym szampanem. Mystery rozwiązane - tylko źle wdrożona metoda testowa. Dzięki jeszcze raz! – IAmYourFaja

2

Guice widzi metodę @Provides i szczęśliwie używa jej do wstrzykiwania Fizz. Jeśli chcesz mieć specjalną instancję Fizz można upuszczać adnotacje ze sposobu providesFizz() i zamiast wiązać z

bind(Fizz.class) 
    .annotatedWith(Names.named("Special-Fizz") 
    .toInstance(providesFizz()); 

ten sposób można powiedzieć Guice które dokładnie Fizz użyć jako „Special-Fizz” nadal pozwalając na wstrzyknięcie Fizz "normalnie" w przeciwnym razie.

Disclaimer: Nie rzeczywiście spróbował konfigurację jak twoje, ale użyłem jednego podobnego. Daj mi znać, czy działa, czy nie.

+0

Dzięki @Bradley T. Hughes (+1) - ** jednak ** Twoja sugestia niczego nie zmienia. Test jednostkowy wciąż mija, niezależnie od tego, jak nazywasz "Fizz". Wspomniałeś coś, co uważałem za interesujące. Powiedziałeś: "* Nie próbowałem takiej konfiguracji jak twoja ... *", jednak z twojej odpowiedzi wywnioskowałem, że wydajesz się dość wygodnie używając Guice. Zastanawiam się więc: * Czy to jest dziwaczna konfiguracja, z której korzystam? * Pomyślałem, że * punktem * Guice było użycie klas i adnotacji razem, aby dokładnie określić, jaki typ/konfigurację chcesz wprowadzić ... – IAmYourFaja

+0

.. Czy robię coś, co jest niezwykłe? Jeśli tak, dlaczego?!? Gdzie nie rozumiem normalnego korzystania z Guice? Dzięki jeszcze raz! – IAmYourFaja

+0

Nie sądzę, że to dziwna konfiguracja. I szczerze mówiąc, nie użyłem Guice tak bardzo, więc z pewnością nie jestem ekspertem.Różnica polega na tym, że kod, nad którym pracuję, korzysta z tej samej adnotacji, aby wstrzykiwać dwa różne typy (po jednym wystąpieniu każdego z nich). –