2017-06-22 11 views
0

Ich versuche, meine Test-Einheit zum Laufen zu bringen, und ich habe ein seltsames Problem festgestellt. Meine Anwendung verwendet eine ApplicationListener-Klasse, die als @Component annotiert ist, um während des Startvorgangs eine Operation auszuführen.Ausschließen eines ApplicationListener @ Component in Spring Boot während der Tests

Während Tests habe ich den Dienst verspottet, der die Logik enthält, aber ich fand, dass, obwohl Mockito, wenn Anweisungen im Controller-Bereich gut funktionieren, die Bean für diese ApplicationListener-Klasse nicht initialisiert wird, anstatt zurückgeben, was ich im Test definieren Einheit gibt es entweder false oder null zurück - abhängig vom Datentyp, der von jeder Methode im Service zurückgegeben wird.

Da ich keine Möglichkeit gefunden habe, den verspotteten Dienst von der Testeinheit für die ApplicationListener-Klasse zu initialisieren, habe ich beschlossen, sie auszuschließen. Dazu habe ich verschiedene Ansätze ausprobiert, die am häufigsten verwendet werden, um einen Testanwendungskontext zu erstellen und seine Konfiguration zu ändern. Leider funktioniert nichts, was ich gesehen habe - also bitte ich um Hilfe. Wenn möglich, würde ich es vorziehen, die ApplicationListener-Klasse nicht zu berühren und alle zugehörigen Kodierungen im Testcode durchzuführen.

Ich interessiere mich für eine der beiden möglichen Lösungen, wenn sie getan werden kann:

1.- das verspottet Verhalten während der Ausführung ApplicationListener, aber ich habe irgendwo, dass diese

getan werden kann, nicht lesen

2.- Schließen Sie die @Component irgendwie von der Testeinheit aus.

TestUnit.Java:

@RunWith(SpringRunner.class) 
@SpringBootTest(classes = TestApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) 
@AutoConfigureMockMvc 
public class TestConfigurationService { 
    private MockMvc mockMvc; 

    @Autowired 
    private WebApplicationContext webApplicationContext; 

    @MockBean 
    private MockService mockService; 

    private void initMockBean() throws Exception { 
     when(mockService.isDoingSomething()).thenReturn(true); 
    } 

    @Before 
    public void setup() throws Exception { 
     // Spring mock context application setup 
     this.mockMvc = webAppContextSetup(webApplicationContext).build(); 

     // Initialize ConsulService mock bean 
     initMockBean(); 
    } 
} 

TestApplication.java

@SpringBootApplication 
@EnableAutoConfiguration 
@ComponentScan(basePackages="my.base.package", excludeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = StartupConfiguration.class)) 
public class TestApplication { 
    public static void main(String[] args) {  
     SpringApplication.run(TestApplication.class, args); 
    } 
} 

Außer dem, was in dem Code angezeigt wird, habe ich auch diese Anmerkung in Datei TestApplication.java versucht:

@SpringBootApplication(exclude={StartupConfiguration.class}) 

StartupConfiguration.java

@Component 
public class StartupConfiguration implements ApplicationListener<ContextRefreshedEvent> { 
    @Autowired 
    private ConfigurationService configurationService; 

    @Override 
    public void onApplicationEvent(final ContextRefreshedEvent event) {  
     try { 
      configurationService.updateConfiguration(); 
     } catch (Exception e) { 
      throw new RuntimeException ("Error", e); 
     } 
    } 
} 

ConfigurationService.java

public interface ConfigurationService { 
    public void updateConfiguration() throws Exception; 
} 

ConfigurationServiceImpl.java

@Service 
@Transactional 
public class ConfigurationServiceImpl implements ConfigurationService {  
    @Autowired 
    private MService mockService; 

    @Override 
    public void updateConfiguration() throws Exception {  
     if (mockService.isDoingSomething()==false) 
      throw new Exception ("Something went wrong"); 
    } 
} 

Versionen:

Frühling Stiefel 1.5.4.RELEASE,

Java 1.8

+0

Ich bin ein wenig verwirrt über das Problem, das Sie haben ... Ist das Problem einfach, dass Spring nicht 'StartupConfiguration' während des Tests initialisieren soll? –

+0

Ich brauche, dass StartupConfiguration für Tests nicht geladen wird, so dass der Listener überhaupt nicht ausgeführt wird. – Rittmann

+0

Eine weitere Alternative könnte sein, dass der Anwendungs-Listener verspottet wird, dass er "true" zurückgibt, aber wenn der innere verspottete Dienst in diesem Moment während des Starts nicht initialisiert wurde, bin ich davon ausgegangen, dass es auch nicht mokierend ist. Aber wenn es möglich wäre, wäre das auch in Ordnung. – Rittmann

Antwort

0

Danke, araxn1d. Ihre Antwort gab mir den Schlüssel zur Lösung dieses Problems.

verspottete ich die Klasse in Startupconfiguration TestUnit.java:

@MockBean 
private StartupConfiguration startupConfiguration; 

Obwohl in diesem Fall hatte ich Glück: Anwendung Zuhörer haben keine Methoden zurückkehren, so brauchen sie nicht, wenn die Testkonfiguration. Wenn ich verlangt hätte, dass eine Methode dort zum Beispiel true oder einen Wert zurückgibt, würde diese Methode nicht angewendet werden.

Aber zumindest für Anwendungshörer, das ist genug.

0

können Sie Mock Bohne des gleichen Typs erstellen und mit @Primary Anmerkung markieren echte Bohne zu ersetzen.Sie können dies durch eine solche Konfiguration Test erreichen:

@Configuration 
@Import(TestApplication.class) 
public class TestConfiguration { 
    @Bean 
    @Primary 
    public ConfigurationService configurationService() { 
     return Mockito.mock(ConfigurationService.class); 
    } 
} 

dann diese Mock in Test erhalten:

... 
public class TestConfigurationService { 
    ... 
    @Autowired 
    ConfigurationService configurationService; 

    @Before 
    public void setUp() { 
     when(mockService.isDoingSomething()).thenReturn(true); 
    } 
} 
+0

Das macht '@ MockBean' schon. Verwechsle es nicht mit '@ Mock' von Mockito. –

+0

@M.Deinum, yep, ich habe es verpasst und meine Antwort hat jetzt überhaupt keinen Wert = ( – rxn1d

Verwandte Themen