0
点赞
收藏
分享

微信扫一扫

单元测试-在弹簧测试上禁用@EnableScheduling

当我运行单元测试时,它会调用我的计划任务。 我想防止这种行为,这是由于我的主应用程序配置中包含@EnableScheduling而引起的。
如何在单元测试中禁用此功能?
我遇到了这个建议设置个人资料的问题/答案。
不知道我该怎么做? 还是过度杀伤力? 我当时在考虑为我的单元测试使用一个单独的AppConfiguration,但是当我这样做时,我感觉好像重复了两次代码吗?
@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

}

单元测试示例。
@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);
    }
}

spring unit-testing junit junit4 springjunit4classrunner
Robbo_UK asked 2020-08-01T10:36:56Z
5个解决方案
42 votes
如果您不想使用配置文件,则可以添加标志以启用/禁用应用程序调度
在您的AppConfiguration中添加此
  @ConditionalOnProperty(
     value = "app.scheduling.enable", havingValue = "true", matchIfMissing = true
  )
  @Configuration
  @EnableScheduling
  public static class SchedulingConfiguration {
  }

在您的测试中,只需添加此注释即可禁用计划
@TestPropertySource(properties = "app.scheduling.enable=false")

Marko Vranjkovic answered 2020-08-01T10:37:24Z
11 votes
另一种选择是取消注册安排事件的bean后处理器。 只需将以下类放在测试的类路径中即可完成此操作:
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);
        }
    }
}

虽然这很简单并且似乎可以完成任务,但是请注意,我并没有对此进行太多测试,也没有检查从注册表中删除已定义的bean或确保PostProcessor的排序不会成为问题的可能的含义...
yankee answered 2020-08-01T10:37:49Z
9 votes
我只是用可配置的延迟时间参数化了@Scheduled注释:
@Scheduled(fixedRateString = "${timing.updateData}", initialDelayString = "${timing.initialDelay}")

在我的测试application.yaml中:
timing:
    updateData: 60000
    initialDelay: 10000000000

和主要application.yaml:
timing:
    updateData: 60000
    initialDelay: 1

它不是关闭它,而是造成了如此长的延迟,测试将在运行之前很长一段时间。 不是最优雅的解决方案,但绝对是我找到的最简单的解决方案之一。
Laila Sharshar answered 2020-08-01T10:38:22Z
2 votes
在每个测试中,您定义应使用的弹簧配置,当前您具有:
@ContextConfiguration(classes={AppConfiguration.class})

常见的做法是为正常应用和测试定义单独的弹簧配置。
AppConfiguration.java 
TestConfiguration.java

然后在测试中,您只需使用@ContextConfiguration(classes={TestConfiguration.class})即可引用TestConfiguration,而不是当前的AppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={TestConfiguration.class})
@Transactional
@TransactionConfiguration(defaultRollback = true)
@WebAppConfiguration
public class ExampleDaoTest

这样,您可以与生产代码中不同的方式为测试配置任何设置。 例如,您可以将内存数据库用于测试,而不是常规数据库。
Vojtech Ruzicka answered 2020-08-01T10:38:56Z
1 votes
通过创建一种在单元测试期间删除计划任务的方法,我能够解决此问题。这是一个例子:
    import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
    import org.springframework.context.ApplicationContext;

    public static void removeSchedulledTasks(ScheduledAnnotationBeanPostProcessor postProcessor, ApplicationContext appContext) {

    postProcessor.setApplicationContext(appContext);

    Iterator<ScheduledTask> iterator = postProcessor.getScheduledTasks().iterator();

    while(iterator.hasNext()) {

        ScheduledTask taskAtual = iterator.next();
        taskAtual.cancel();

    }

}

使用示例:
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.example.Utils;


@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRemoveScheduller {


    @Autowired
    private ScheduledAnnotationBeanPostProcessor postProcessor;

    @Autowired
    private ApplicationContext appContext;


    @Before
    public void init(){

        //Some init variables

        //Remove schedulled tasks method
        Utils.removeSchedulledTasks(postProcessor, appContext);

    }

    //Some test methods

}

希望这可以帮助。

举报

相关推荐

0 条评论