2015-03-30 10 views
22
@RunWith(SpringJUnit4ClassRunner.class) 
public void ITest { 
    @Autowired 
    private EntityRepository dao; 

    @BeforeClass 
    public static void init() { 
     dao.save(initialEntity); //not possible as field is not static 
    } 
} 

Wie kann ich meinen Dienst bereits in die statische Init-Klasse injiziert bekommen?Wie man Feld in statischem @BeforeClass autowire?

+3

Dieser Blog-Eintrag können Ihnen helfen, ausgeführt überspringen wird - http: //saltnlight5.blogspot .in/2012/09/enhancing-spring-test-framework-with.html – Mithun

Antwort

7

Es sieht für mich aus, dass Sie versuchen, DB vor Tests zu füllen.

würde ich einen Versuch zu zwei Möglichkeiten geben:

  • Wenn Sie Anfangs Skripte SQL-Datei extrahieren kann (wenn diese Option für Sie ist ohne Verwendung von Repository-Bean) Sie können this approach verwenden und mit Anmerkungen versehen Test mit @Sql
  • Sie können DbUnit erforschen und hier ist link to spring dbunit connector, die genau das tut und Ihnen helfen, DB vor Tests zu füllen. Hier ist ein github link für die Integration zwischen Federtest Framework und dbunit. Nachdem Sie das tun, haben Sie @DatabaseSetup und @DatabaseTearDown die Sache auf DB tun müssen Sie

Ich weiß, dass dies, wie Bohne in Code statische @BeforeClass aber Form zu injizieren, nicht antwortet sieht es es Ihr Problem zu lösen.

Update: ich in gleiches Problem in meinem Projekt vor kurzem laufen und ausgegraben this article, die mir geholfen, und ich denke, es ist elegant Art und Weise ist bei dieser Art von Problem umzugehen. Sie können SpringJUnit4ClassRunner mit einem Listener erweitern, der auf Instanzebene mit allen Ihren definierten Beans arbeiten kann.

2

Um diese Frage zu beantworten, sollten wir Spring 2.x-Versionen wiederholen.

Wenn Sie eine Bean in Ihrer @BeforeTest Klasse "autowire" möchten, können Sie die ApplicationContext Schnittstelle verwenden. Nehmen wir ein Beispiel sehen:

@BeforeClass 
    public static void init() { 
     ApplicationContext context = new ClassPathXmlApplicationContext("application-context.xml"); 
     EntityRepository dao2 = (EntityRepository) context.getBean("dao"); 
     List<EntityRepository> all = dao2.getAll(); 
     Assert.assertNotNull(all); 
    } 

Was geschieht: die ClassPathXmlApplicationContext benutzen wir alle Bohnen in der application-context.xml Datei enthalten sind, instanziieren.

Mit context.getBean() lesen wir die angegebene Bean (es muss den Namen der Bean übereinstimmen!); und dann können Sie es für Ihre Initialisierung verwenden.

Sie sollten der Bohne einen anderen Namen geben (das ist die dao2!) Sonst kann Spring normal "autowired" nicht mit der vordefinierten Bean arbeiten.

Als eine Randnotiz, wenn Ihr Test AbstractTransactionalJUnit4SpringContextTests erweitert, können Sie einige Initialisierung mit executeSqlScript(sqlResourcePath, continueOnError); Methode, so dass Sie nicht auf eine Klasse/Methode angewiesen sind, die Sie auch separat testen müssen.

+0

Ich kann den 'ApplicationContext' nicht selbst instanziieren, da ich auch' @ IntegrationTest' verwende, um meine normalen '@ EnableAutoConfiguration' Klassen während des Tests zu aktivieren (annotation-based config). – membersound

+0

Warum verwenden Sie das 'executeSqlScript' dann nicht?Es ist eine statische Methode, die Sie kostenlos erhalten, wenn Sie die Klasse 'AbstractTransactionalJUnit4SpringContextTests' erweitern. – musikele

+0

Die Frage ist natürlich nur ein Beispiel. Ich könnte auch jede Logik in @BeforeClass ausführen müssen, nicht nur die Datenbankinitialisierung ... – membersound

9

Eine Abhilfe, die ich habe mit dieser Funktion zu erhalten ist @Before mit einem Flag zu verwenden, um es für jeden Testfall

@RunWith(SpringJUnit4ClassRunner.class) 
public class BaseTest { 

@Autowired 
private Service1 service1; 

@Autowired 
private Service2 service2; 

private static boolean dataLoaded = false; 

@Before 
public void setUp() throws Exception { 

    if (!dataLoaded) { 
     service1.something(); 
     service2.somethingElse(); 
     dataLoaded = true; 
    } 
    } 
} 
+2

Ich mache das weiter, aber es muss wirklich einen besseren Weg geben, besonders wenn man sich auf ein injected/autowired Feld verlässt, denn in diesem Fall wird '@ BeforeClass' nicht funktionieren. – carlspring

+0

Was ist mit dem @ AfterClass Teil nach der Ausführung Ihrer Tests. Jede Strategie, um es einfach zu halten, wie dieser erste Teil? – emecas