Ho fatto un bel po 'di ricerche online e non riesco a trovare un esempio di test unitario con un costruttore autowired. Sto usando Spring per autowire nei valori da un file delle proprietà alla mia applicazione. Voglio testare unitamente il metodo di avvio di MyApp.java, ma ho un costruttore autowired quindi non so come istanziare MyApp. Senza le proprietà autowired, stavo facendo questo nel mio test di unità:Come posso JUnit testare un costruttore autowired di Spring?
@Test
public void testStart() {
try{
MyApp myApp = new MyApp();
myApp.start();
}
catch (Exception e){
fail("Error thrown")
}
}
Non voglio prendere in giro l'autowiring, come ho bisogno di ottenere i valori dal file delle proprietà e per complicare ulteriormente le cose, io sono configurazione di tutto tramite annotazioni. Non ho un file spring.xml, application-context.xml o web.xml. Quindi, come faccio a istanziare/testare il metodo di avvio di MyApp? Ho provato ad aggiungere in @RunWith (SpringJUnit4ClassRunner.class) e ad attivare MyApp myApp, ma genera errori sul mancato caricamento del contesto dell'applicazione che non viene risolto implementando ApplicationContextAware nella classe di test.
Ecco MyApp.java
@Component
public class MyApp {
private static ApplicationContext applicationContext;
private static MyAppProperties myAppProperties;
//Obtain the values from the app.properties file
@Autowired
MyApp(MyAppProperties myAppProps){
myAppProperties = myAppProps;
}
public static void main(String[] args) throws Exception {
// Instantiate the application context for use by the other classes
applicationContext = new AnnotationConfigApplicationContext("com.my.company");
start();
}
/**
* Start the Jetty server and configure the servlets
*
* @throws Exception
*/
public static void start() throws Exception {
// Create Embedded Jetty server
jettyServer = new Server();
// Configure Jetty so that it stops at JVM shutdown phase
jettyServer.setStopAtShutdown(true);
jettyServer.setStopTimeout(7_000);
// Create a list to hold all of the handlers
final HandlerList handlerList = new HandlerList();
// Configure for Http
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(myAppProperties.getHTTP_SECURE_PORT());
....
}
}
Qui è il file miei app.properties
# Spring Configuration for My application
#properties for the embedded jetty server
http_server_port=12345
Ecco MyAppProperties.java
@Component
public class MyAppProperties implements ApplicationContextAware {
private ApplicationContext applicationContext;
//List of values from the properties files to be autowired
private int HTTP_SERVER_PORT;
...
@Autowired
public MyAppProperties(@Value("${http_server_port}") int http_server_port, ...){
this.HTTP_SERVER_PORT = http_server_port;
}
/**
* @return the applicationContext
*/
public ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* @param applicationContext
* the applicationContext to set
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
/**
* @param name
* the name to set
*/
public void setHTTP_SERVER_PORT(String name) {
JETTY_SERVER_NAME = name;
}
/**
* @return the httpServerPort
*/
public int getHTTP_SERVER_PORT() {
return HTTP_SERVER_PORT;
}
}
Ecco MyAppTest.java
@RunWith(SpringJUnit4ClassRunner.class)
public class MyAppTest implements ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext appContext) {
applicationContext = appContext;
}
@Autowired
private MyApp myapp;
@Test
public void testStart(){
try {
if(myapp != null){
myapp.start();
}
else{
fail("myapp is null");
}
} catch (Exception e) {
fail("Error thrown");
e.printStackTrace();
}
}
}
AGGIORNAMENTO: Ecco la mia classe di configurazione
@Configuration
@Component
public class ApplicationConfig implements ApplicationContextAware {
private final Logger LOGGER = LoggerFactory.getLogger(ApplicationConfig.class);
private ApplicationContext applicationContext;
/**
* @return the applicationContext
*/
public ApplicationContext getApplicationContext() {
LOGGER.debug("Getting Application Context", applicationContext);
return applicationContext;
}
/**
* @param applicationContext
* the applicationContext to set
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
// Needed for @Value
/**
* Property sources placeholder configurer.
*
* @return the property sources placeholder configurer
*/
@Bean
public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer() {
PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
propertyPlaceholderConfigurer.setLocation(new ClassPathResource("app.properties"));
return propertyPlaceholderConfigurer;
}
...
}
L'aggiunta di '@ RunWith' e senza indicare quale configurazione caricare non funzionerà. Devi aggiungere una 'public static class' alla tua classe di test mettendo' @ Configuration' e '@ComponentScan (" your.package ")' su di esso. Ad un ulteriore livello suggerirei di utilizzare Spring Boot anche per il bootstrap dell'applicazione e per iniettare/usare le proprietà come sembra che stiano facendo esattamente ciò che Spring Boot fornisce out-of-the-box (incluso il supporto di test per questo). –
@ M.Deinum Sfortunatamente, Spring Boot non è un'opzione per me a causa di conflitti con altri strumenti. Giusto per chiarire, stai dicendo che dovrei cambiare la mia classe di test in public class class MyAppTest o dovrei fare un'altra lezione? Quando provo a rendere statica la classe MyAppTest, viene visualizzato un messaggio di errore che indica che si tratta di un modificatore non valido. – jencoston
No, è necessario aggiungere una classe di configurazione interna.Inoltre non vedo alcuna differenza in ciò che Spring Boot fa con il ridere di un server interno come fai tu stesso, non ci dovrebbe essere alcuna differenza. –