2016-01-29 17 views
5

Wir haben eine Frühling auf Basis JUnit-Testklasse, die Konfiguration, die eine innere TestkontextklasseVerwenden Sie unterschiedliche Federtestkontextkonfiguration für unterschiedliche Testmethoden

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes = ServiceTest.Config.class) 
public class ServiceTest { 

    @Test 
    public void someTest() { 
    ... 

    @Configuration 
    @PropertySource(value = { "classpath:application.properties" }) 
    @ComponentScan({ "..." }) 
    public static class Config { 
    ... 

Neue Funktionalitäten wurden kürzlich an die Service-Klasse eingeführt, für welche Verwendung Die betreffenden Tests sollten ServiceTest hinzugefügt werden. Dies würde jedoch auch erfordern, dass eine andere Testkontextkonfigurationsklasse erstellt wird (die Interna der vorhandenen Config-Klasse sind ziemlich komplex und ändern sich, um sowohl alte als auch neue Tests zu bedienen, scheint extrem schwierig zu sein)

Gibt es eine Möglichkeit zu erreichen, dass bestimmte Testmethoden in einer Testklasse eine Konfigurationsklasse verwenden und andere Methoden eine andere verwenden? @ContextConfiguration scheint nur auf Klassenebene anwendbar zu sein, so dass die Lösung darin bestehen könnte, eine weitere Testklasse für die neuen Tests zu erstellen, die ihre eigene Kontextkonfigurationsklasse verwenden würde; aber es würde bedeuten, dass die gleiche Service-Klasse wird über zwei verschiedene Testklassen

Antwort

1

ich diese Ansätze verwenden abgedeckt ist, wenn ich dies habe zu lösen:

  • manuell bauen den Kontext, in einem Setup-Methode statt Anmerkungen verwenden.
  • Verschieben Sie den allgemeinen Testcode in eine Basisklasse und erweitern Sie ihn. Dadurch kann ich die Tests mit unterschiedlichen Federkontexten durchführen.
  • Eine Mischung aus den beiden oben. Die Basisklasse enthält dann Methoden zum Erstellen von Springkontexten aus Fragmenten (die die Erweiterungen überschreiben können). Das erlaubt mir auch, Testfälle zu überschreiben, die bei einigen Tests keinen Sinn machen oder zusätzliche Vor-/Nacharbeiten erfordern.

Beachten Sie, dass Annotationen nur allgemeine Fälle lösen. Wenn Sie die gemeinsame Basis verlassen, müssen Sie einige oder alle ihrer Arbeiten wiederholen.

+0

Aber funktioniert die Autowired-Einspritzung in der Basisklasse, wenn wir sie manuell einrichten? – pinkpanther

+0

@pinkpanther: Sie verwechseln das Test-Setup mit dem getesteten Code. Das Testsetup verwendet nicht '@ Autowired'. Ich vermeide die Injektion in Tests, wenn ich kann: Es verlangsamt die Tests und macht es schwieriger zu sehen, was vor sich geht. Wenn IDEs "zeige mir, was hier injiziert wird, wenn ich den Test ausführe", werde ich meine Meinung ändern. –

4

Mit dem Vorschlag von Aaron, den Kontext manuell zu erstellen, konnte ich keine guten Beispiele finden, also habe ich nach einiger Zeit eine einfache Version des Codes veröffentlicht, falls jemand anderen hilft:

class MyTest { 

    @Autowired 
    private SomeService service; 
    @Autowired 
    private ConfigurableApplicationContext applicationContext; 

    public void init(Class<?> testClass) throws Exception { 
     TestContextManager testContextManager = new TestContextManager(testClass); 
     testContextManager.prepareTestInstance(this); 
    } 

    @After 
    public void tearDown() throws Exception { 
     applicationContext.close(); 
    } 

    @Test 
    public void test1() throws Exception { 
     init(ConfigATest.class); 
     service.doSomething(); 
     // assert something 
    } 

    @Test 
    public void test2() throws Exception { 
     init(ConfigBTest.class); 
     service.doSomething(); 
     // assert something 
    } 

    @ContextConfiguration(classes = { 
     ConfigATest.ConfigA.class 
    }) 
    static class ConfigATest { 
     static class ConfigA { 
      @Bean 
      public SomeService someService() { 
       return new SomeService(new A()); 
      } 
     } 
    } 

    @ContextConfiguration(classes = { 
     ConfigBTest.ConfigB.class 
    }) 
    static class ConfigBTest { 
     static class ConfigB { 
      @Bean 
      public SomeService someService() { 
       return new SomeService(new B()); 
      } 
     } 

    } 
} 
Verwandte Themen