为什么Akka Streams TestSource没有收到每个pull作为请求?

时间:2016-12-08 22:45:02

标签: scala scalatest akka-stream

我正在尝试追踪自定义Flow中的一个错误,其中有额外的请求上行。我写了一个测试用例,考虑到我所看到的行为和日志记录应该失败,但它没有。

然后我做了一个微不足道的Flow,有一个明显的额外拉力,但测试仍然没有失败。

以下是一个例子:

class EagerFlow extends GraphStage[FlowShape[String, String]] {

  val in: Inlet[String] = Inlet("EagerFlow.in")
  val out: Outlet[String] = Outlet("EagerFlow.out")

  override def shape: FlowShape[String, String] = FlowShape(in, out)

  override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
    setHandler(in, new InHandler {
      override def onPush() = {
        println("EagerFlow.in.onPush")
        println("EagerFlow.out.push")
        push(out, grab(in))
        println("EagerFlow.in.pull")
        pull(in)
      }
    })
    setHandler(out, new OutHandler {
      override def onPull() = {
        println("EagerFlow.out.onPull")
        println("EagerFlow.in.pull")
        pull(in)
      }
    })
  }
}

这是一个应该通过的测试,即确认有额外的请求。

"Eager Flow" should "pull on every push" in {
  val sourceProbe = TestSource.probe[String]
  val sinkProbe = TestSink.probe[String]

  val eagerFlow = Flow.fromGraph(new EagerFlow)

  val (source, sink) = sourceProbe.
    via(eagerFlow).
    toMat(sinkProbe)(Keep.both).
    run

  sink.request(1)
  source.expectRequest()
  source.expectNoMsg()

  source.sendNext("hello")
  sink.expectNext()
  source.expectRequest()
}

在标准输出中,您可以看到:

0C3E08A8 PULL DownstreamBoundary -> TestSpec$EagerFlow@1d154180 (TestSpec$EagerFlow$$anon$4$$anon$6@7e62ecbd) [TestSpec$EagerFlow$$anon$4@36904dd4]
EagerFlow.out.onPull
EagerFlow.in.pull
0C3E08A8 PULL TestSpec$EagerFlow@1d154180 -> UpstreamBoundary (BatchingActorInputBoundary(id=0, fill=0/16, completed=false, canceled=false)) [UpstreamBoundary]
EagerFlow.in.onPush
EagerFlow.out.push
EagerFlow.in.pull
0C3E08A8 PULL TestSpec$EagerFlow@1d154180 -> UpstreamBoundary (BatchingActorInputBoundary(id=0, fill=0/16, completed=false, canceled=false)) [UpstreamBoundary]

assertion failed: timeout (3 seconds) during expectMsg:
  java.lang.AssertionError: assertion failed: timeout (3 seconds) during expectMsg:
  at scala.Predef$.assert(Predef.scala:170)
at akka.testkit.TestKitBase$class.expectMsgPF(TestKit.scala:368)
at akka.testkit.TestKit.expectMsgPF(TestKit.scala:737)
at akka.stream.testkit.StreamTestKit$PublisherProbeSubscription.expectRequest(StreamTestKit.scala:665)
at akka.stream.testkit.TestPublisher$Probe.expectRequest(StreamTestKit.scala:172)

(这是akka.stream.impl.fusing.GraphInterpreter#processEvent中的调试日志记录,实际上是使用打印点,但实际上是相同的事情)

为什么这种情况会在UpstreamBoundary停止并且永远不会回到TestSource.probe

我有很多测试使用expectNoMsg()来确保正确的背压,但似乎这些只会给出误报。如果这不起作用,我该如何测试呢?

1 个答案:

答案 0 :(得分:1)

要使测试适用,您需要将Flow缓冲区设置为1。

val settings = ActorMaterializerSettings(system)
  .withInputBuffer(initialSize = 1, maxSize = 1)
implicit val mat = ActorMaterializer(settings)

默认尺寸为:

  # Initial size of buffers used in stream elements
  initial-input-buffer-size = 4
  # Maximum size of buffers used in stream elements
  max-input-buffer-size = 16

这意味着Akka会在您第一次请求时急切地请求并摄取最多16个元素 。有关内部缓冲区的更多信息可以在source找到。