2015-03-12 5 views
20

Wenn ich meine Komponententests ausführen, ruft es meine geplanten Aufgaben auf. Ich möchte dieses Verhalten verhindern, das durch die Tatsache verursacht wird, dass ich @EnableScheduling in meiner Haupt-App-Konfiguration habe.Deaktivieren Sie @EnableScheduling bei Spring Tests

Wie kann ich dies bei meinen Komponententests deaktivieren?

Ich bin auf diese question/answer gestoßen, die das Einrichten von Profilen vorschlägt?

Nicht sicher, wie ich das machen würde? oder wenn es ein Overkill ist? Ich dachte daran, eine separate AppConfiguration für meine Unit-Tests zu haben, aber es fühlt sich an, als würde ich Code zweimal wiederholen, wenn ich das tue?

@Configuration 
@EnableJpaRepositories(AppConfiguration.DAO_PACKAGE) 
@EnableTransactionManagement 
@EnableScheduling 
@ComponentScan({AppConfiguration.SERVICE_PACKAGE, 
       AppConfiguration.DAO_PACKAGE, 
       AppConfiguration.CLIENT_PACKAGE, 
       AppConfiguration.SCHEDULE_PACKAGE}) 
public class AppConfiguration { 

    static final String MAIN_PACKAGE    = "com.etc.app-name"; 
    static final String DAO_PACKAGE    = "com.etc.app-name.dao"; 
    private static final String ENTITIES_PACKAGE = "com.etc.app-name.entity"; 
    static final String SERVICE_PACKAGE   = "com.etc.app-name.service"; 
    static final String CLIENT_PACKAGE   = "com.etc.app-name.client"; 
    static final String SCHEDULE_PACKAGE   = "com.etc.app-name.scheduling"; 


    @Bean 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
     // stripped code for question readability 
    } 

    // more app config code below etc 

} 

Testeinheit Beispiel.

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes={AppConfiguration.class}) 
@Transactional 
@TransactionConfiguration(defaultRollback = true) 
@WebAppConfiguration 
public class ExampleDaoTest { 

    @Autowired 
    ExampleDao exampleDao; 

    @Test 
    public void testExampleDao() { 
     List<Example> items = exampleDao.findAll(); 
     Assert.assertTrue(items.size()>0); 
    } 
} 
+0

Warum wollen Sie Feder Rahmen für Unit-Tests benutzen? –

+0

, so dass es meine Objekte autowires, so dass ich meine Daos und Dienste testen kann? –

+0

Du könntest den Dao nur verspotten. Am besten wäre ein Framework wie Mockito. –

Antwort

16

Wenn Sie keine Profile verwenden möchten, können Sie ein Flag hinzufügen, das die Planung für die Anwendung

In Ihrem AppConfiguration fügen Sie diese

hinzu
@ConditionalOnProperty(
    value = "app.scheduling.enable", havingValue = "true", matchIfMissing = true 
) 
    @Configuration 
    @EnableScheduling 
    public static class SchedulingConfiguration { 
    } 

und in Ihrem Test fügen Sie einfach diese Anmerkung Planung deaktivieren

@TestPropertySource(properties = "app.scheduling.enable=false") 
+1

irgendwie hat es meine Spring-Boot-Konfigurationen – Hinotori

+1

getötet Beachten Sie, dass externe Komponenten könnte die Planung automatisch aktivieren (siehe HystrixStreamAutoConfiguration und MetricExportAutoConfiguration aus dem Spring Framework). Wenn Sie versuchen, '@ ConditionalOnProperty' oder' @Profile' in der Klasse '@Configuration' zu verwenden, die' @EnableScheduling' angibt, wird die Planung aufgrund externer Komponenten trotzdem aktiviert. siehe https://Stackoverflow.com/a/46783392/2947239 – Sisyphus

+0

Sisyphus macht den gleichen Punkt, den ich machen würde. Ich würde hinzufügen, dass MetricExportAutoConfiguration von Spring Boot Actuator stammt und in einem Testprofil deaktiviert wird mit: spring.metrics.export.enabled: false –

2

In jedem Test, den Sie zur Zeit der Federkonfiguration definieren soll verwendet werden, Sie haben:

@ContextConfiguration(classes={AppConfiguration.class}) 

Gängige Praxis ist separate Federkonfiguration für Ihre normale Anwendung und für Ihre Tests zu definieren.

AppConfiguration.java 
TestConfiguration.java 

Dann in Ihrem Test refference Sie einfach TestConfiguration anstelle Ihrer aktuellen AppConfiguration@ContextConfiguration(classes={TestConfiguration.class})

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes={TestConfiguration.class}) 
@Transactional 
@TransactionConfiguration(defaultRollback = true) 
@WebAppConfiguration 
public class ExampleDaoTest 

Auf diese Weise verwenden Sie eine Einstellung für Ihre Tests konfigurieren können anders als in Produktionscode. Sie können zum Beispiel in-Memory-Datenbank für Ihre Tests anstelle von regulären und viel mehr verwenden.

+3

Leider funktioniert es nicht so. Der Test verwendet die TestConfiguration-Klasse, verwendet jedoch weiterhin die in der TestConfiguration deklarierten Annotationen.:( – ali

+0

Sie können eine Testkonfigurationsklasse oder aktive Profile einrichten, die aus der Eigenschaftendatei abgerufen werden, dabei vermeiden Sie jedoch nicht, dass die mit Anmerkungen versehene Klasse geplant wird. –

+1

http://stackoverflow.com/questions/40226937/planed-method-is-called-within-the-tests - Dieser hat bei mir funktioniert –

4

Eine Alternative wäre die Aufhebung der Registrierung des Bean-Post-Prozessors, der die Ereignisse plant. Dies kann einfach dadurch geschehen, dass die folgende Klasse im Klassenpfad Ihrer Tests setzen:

public class UnregisterScheduledProcessor implements BeanFactoryPostProcessor { 

    @Override 
    public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) throws BeansException { 
     for (String beanName : beanFactory.getBeanNamesForType(ScheduledAnnotationBeanPostProcessor.class)) { 
      ((DefaultListableBeanFactory)beanFactory).removeBeanDefinition(beanName); 
     } 
    } 
} 

Während dies ganz einfach und scheint die Arbeit zu tun, aufpassen, dass ich das nicht testen, habe sehr viel und mögliche Auswirkungen überprüfen Entfernen eines definierten Beans aus der Registry oder Sicherstellen, dass die Bestellung von PostProcessors kein Problem ist ...

+1

Nur um ein Feedback zu geben - ich habe gerade diese Methode ausprobiert und es scheint gut zu funktionieren. – RockMeetHardplace

+0

Ich habe versucht @ vojtech-ruzicka und @ lolotron Antworten plus andere Antworten auf [diese ähnliche Frage hier] (https://stackoverflow.com/questions/40226937/scheduled-method-is-called-during-the-tests) Ebenso muss ich hinzufügen, dass nur @yankee Antwort funktionierte für mich.Mit einer '@ Configuration' Annotation in seinem Beispiel' UnregisterScheduledProcessor '-Klasse für es automatisch von Spring unter meinem Test geladen werden.Ich habe bisher nicht e Erfahrung mit irgendwelchen Problemen damit. – DaddyMoe