gui*_*ebl 5 testing scala scheduled-tasks akka playframework
我的应用程序基于 Scala Play 框架,它有一个计划的作业,每次加载应用程序时都会运行:
// 代码片段:
actorSystem.scheduler.schedule(initialDelay = 0.second, interval = intervalSeconds.second)
Run Code Online (Sandbox Code Playgroud)
在测试期间,如果我启用计划作业,所有测试都会正常完成并且结果通过(绿色),但我看到日志中随机出现异常:
[TaskInspiration] 尝试在物化器关闭后物化流 java.lang.IllegalStateException:在 akka.stream.impl.PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:424) 处关闭物化器后尝试物化流 akka.stream.impl .PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:417)在akka.stream.impl.PhasedFusingActorMaterializer.materialize(PhasedFusingActorMaterializer.scala:408)在akka.stream.scaladsl.RunnableGraph.run(Flow.scala:556)在akka.stream。 scaladsl.Source.runWith(Source.scala:103) 在 play.api.libs.streams.StrictAccumulator.run(Accumulator.scala:203) 在mockws.FakeWSRequestHolder.executeResult(FakeWSRequestHolder.scala:118) 在mockws.FakeWSRequestHolder.execute (FakeWSRequestHolder.scala:103) 在mockws.FakeWSRequestHolder.execute(FakeWSRequestHolder.scala:188) 在mockws.FakeWSRequestHolder.get(FakeWSRequestHolder.scala:181)
我正在使用一个 Web 服务模拟库:https://github.com/leanovate/play-mockws ,该错误似乎与该库在测试期间如何使用和释放 ActorSystem 物化器实例有关。对于与参与者系统相关的测试配置,我有:
MockWSHelpers 内的代码:
trait MockWSHelpers {
private val actorSystem: ActorSystem = actor.ActorSystem("unit-testing")
implicit val materializer: ActorMaterializer = ActorMaterializer()(actorSystem)
val BodyParser: PlayBodyParsers = PlayBodyParsers()
val Action: DefaultActionBuilder = DefaultActionBuilder(BodyParser.anyContent)
def shutdownHelpers(): Unit = {
materializer.shutdown()
Await.result(actorSystem.terminate(), 3.minutes)
}
}
object MockWSHelpers extends MockWSHelpers {
sys addShutdownHook {
shutdownHelpers()
}
}
Run Code Online (Sandbox Code Playgroud)
所有测试都将从以下继承的基测试类:
abstract class BaseDomainTest extends PlaySpec with MockitoSugar with MockWSHelpers with BeforeAndAfterAll {
override def afterAll(): Unit = {
shutdownHelpers()
}
}
Run Code Online (Sandbox Code Playgroud)
域测试类将扩展 BaseDomainTest,例如:
@RunWith(classOf[JUnitRunner])
class MyTestDomainControllerSpec extends BaseDomainTest {
Run Code Online (Sandbox Code Playgroud)
我的印象是,有时计划的作业在 MockWSHelpers 的关闭钩子结束之前没有完成,并且抛出异常,当它在之前完成时,没有异常。
如何避免上述异常呢?
替代方法:
一种替代方法是在测试期间完全禁用计划的作业,并将其内部业务逻辑移至完全独立的类中。例子:
预定任务:
actorSystem.scheduler.schedule(initialDelay = 0.Second, Interval = IntervalSeconds.Second) { if (config.isJobEnabled) { myBusinessObject.execute() } }
在这种情况下,仅进行myBusinessObject.execute()隔离测试,并且在测试期间不启用计划任务。