2013-10-18 4 views
5

Ich habe eine statische Spring 3.2.4 Bean mit einer geschützten @ PostConstruct-Methode, die Daten aus einem DB beim Initialisieren lädt.So verzögern Aufruf von @PostConstruct, bis jUnit Testkontext eingerichtet hat

Beim Erstellen eines jUnit-Tests möchte ich in meinen Testmethoden die Daten in der Datenbank einrichten, um die Bean entsprechend zu testen. Da jedoch die Bean vor meinen Testmethoden instanziiert wird, weiß ich nicht, wie Spring angefordert wird, um die Instanziierung der Bean zu verzögern, bis die Methode abgeschlossen ist.

Da die @ PostConstruct-Methode geschützt ist, kann ich sie nicht direkt aufrufen, um die Bean erneut zu initialisieren, es sei denn, ich verwende Reflektion.

Gibt es einen anderen Weg, dies zu tun, oder ist Reflektion der einzige Weg? Hat Spring irgendwelche Util-Klassen, um es einfacher zu machen, oder muss ich Standard-Java-Reflektion verwenden?

Antwort

2

Sie können den Kontext für diesen Anwendungsfall immer programmgesteuert starten. Beachten Sie, dass Sie in diesem Fall für den Lebenszyklus des Kontexts verantwortlich sind. Der folgende Pseudocode veranschaulicht das:

@Test 
public void yourTest() { 
    // setup your database 

    ConfigurableApplicationContext context = 
     new ClassPathXmlApplicationContext("/org/foo/your-context.xml"); 
    // Or new AnnotationConfigApplicationContext(YourConfig.class) 
    try { 
     YourBean bean = context.getBean("beanId"); 
     // Assertions 
    } finally { 
     context.close(); 
    } 
} 

Sie benötigen wahrscheinlich Spring, um Ihre Datenbank zu initialisieren. Sie könnten zum Beispiel die reguläre Spring-Test-Kontextunterstützung verwenden, um nur die Beans zu initialisieren, die Sie für die Datenbankeinrichtung benötigen, und einen weiteren Kontext programmatisch starten, um Ihren Service zu bestätigen. Wenn dieser Kontext einige Dienste benötigt, die für die Datenbank-Initialisierung verwendet wurden, können Sie ein Kind Kontext beginnen stattdessen so etwas wie

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration // for instance FooTest-context.xml 
public class FooTest { 

    @Autowired 
    private ApplicationContext mainContext; 

    @Test 
    public void yourTest() { 
     // setup your database 

     ClassPathXmlApplicationContext context = 
       new ClassPathXmlApplicationContext(); 
     context.setParent(mainContext); 
     context.setConfigLocation("/org/foo/your-context.xml"); 
     context.refresh(); 
     try { 
      YourBean bean = context.getBean("beanId"); 
      // Assertions 
     } finally { 
      context.close(); 
     } 
    } 
} 

Wenn das ein wiederkehrender Anwendungsfall werden Sie eine Template-Methode erstellen, die die Container starten und aufrufe eine Callback-Schnittstelle. Auf diese Weise können Sie das Context Lifecycle Management an einem zentralen Ort nutzen.

+0

Danke. Am Ende habe ich mich mit dem Problem herumgeschlagen, aber deine Lösung gibt mir definitiv eine andere Möglichkeit, es zu betrachten. –

Verwandte Themen