【问题标题】:Poor JUnit test using springframework has fragile Thread.sleep() calls. How to fix?使用 springframework 的不良 JUnit 测试具有脆弱的 Thread.sleep() 调用。怎么修?
【发布时间】:2010-12-13 20:57:00
【问题描述】:

我最近加入了一个有一些严重 JUnit 测试问题的小组。一个问题是 8 分钟的测试!测试有几个部分;每个都调用 org.springframework.context.ApplicationEventPublisher.publishEvent() 然后是不同时间的 Thread.sleep(),然后测试条件。

这种方法有几个明显的问题,Thread.sleep() 调用的时机很脆弱:

  • 在繁忙的机器上测试偶尔会失败;和

  • 没有失败的测试花费的时间太长了。

处理这些事件的池是否可用于测试?是否有调用以查看事件级联是否已停止?

【问题讨论】:

    标签: java multithreading spring-test


    【解决方案1】:

    值得一提的是,实际调用外部服务的测试代码是集成测试,而不是单元测试。如果你真的在这里进行单元测试,你应该用模拟替换那些调用。这样,您可以更好地控制返回到业务逻辑的值并测试特定条件。此外,正如您所见,这几乎消除了由于外部(非代码)情况导致的误报。显然,这些测试并没有失败,他们期望使用的工具是。

    【讨论】:

    • +1 我认为这是基本问题的答案。模拟掉外部,测试会运行得更快。
    • 是的,我知道这不是单元测试,而是集成测试。任何人都可以帮助我解决有关加快此集成测试的问题。 (不是我写的。我只是想快点。)
    【解决方案2】:

    您可以通过将此 bean id 添加到您的应用程序上下文来覆盖默认的 applicationEventMulticaster

    除了默认的SimpleApplicationEventMulticaster,您可以在这个bean 上设置一个TaskExecutor 以在多个线程中异步执行事件发布。

    或者您可以实现自己的多播器,它会打印出哪个事件侦听器花了这么长时间或阻塞了多长时间以及发生了哪些事件。这可以帮助您找出 8 分钟测试用例的真正问题。

    有趣的是,Spring 在使用 ApplicationContext 时默认使用的 SimpleApplicationEventMulticaster 的 JavaDoc 声明如下:

    默认情况下,所有侦听器都在调用线程中调用。 这允许恶意侦听器阻塞整个应用程序的危险,但增加的开销最小。指定一个替代的 TaskExecutor 让监听器在不同的线程中执行,例如从一个线程池中。

    【讨论】:

      【解决方案3】:

      我(故意)避免使用 Spring,所以我不确定我是否可以帮助解决具体问题,但只是查看睡眠问题,您可以在 tempus-fugit(无耻插件)中使用 WaitFor 之类的东西来轮询 @ 987654323@而不是“睡觉和希望”。这并不理想,通常最好改变您的测试方式(如前所述),但这确实意味着您可以获得更细粒度的“等待”,这更有可能避免竞争条件/片状测试并通常加快测试速度。

      查看项目的documentation 了解详细信息,如果您觉得有用,请回帖!

      【讨论】:

        猜你喜欢
        • 2010-10-02
        • 2014-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-22
        • 1970-01-01
        • 2014-02-26
        相关资源
        最近更新 更多