首页 > 解决方案 > 在 Pony 中结束所有行为后运行函数/行为

问题描述

我有一个简单的发布订阅者,我想为其编写测试。这里调用的方法都是行为,除了get_number_consumed_messages那是一个函数。

class iso _SinglePubSub is UnitTest
    fun name(): String => "single publish/consume"

    fun apply(h: TestHelper) =>
        let p = Publisher("publisher message", h.env.out)
        let queue = Queue(1, h.env.out)
        let c = Consumer(h.env.out)

        p.publish_message(queue)
        p.publish_message(queue)
        c.consume_message(queue)
        c.consume_message(queue)

        //Run after all behaviours are done
        let n = c.get_number_consumed_messages()
        h.assert_eq[USize](2, n)

有人将如何实现get_number_consumed_messages功能/行为,或者您将如何修改测试功能?

标签: unit-testingtestingpublish-subscribeponylang

解决方案


首先,c.get_number_consumed_messages()必须是一种行为。这是让一个演员与另一个演员交流的唯一方法。这具有额外的好处,即行为以与调用它们相同的顺序运行,这意味着c.get_number_consumed_messages()将在两次调用之后运行c.consume_message(queue)

鉴于此,sinceConsumer也是一个参与者,用行为而不是方法调用它意味着我们不能直接从它返回数据。要实际接收来自其他参与者的数据,您应该使用Promise 模式,例如:

use "promises"

actor Consumer
  var message_count: USize = 0

  be consume_message(queue: OutStream) =>
    ... // Do some things
    message_count = message_count + 1
    ... // Do other things

  be get_number_consumed_messages(p: Promise[USize]) =>
    p(message_count)

要实际测试它,您需要遵循测试通知程序交互模式改编版本进行长时间测试,例如:

use "ponytest"
use "promises"

class iso _SinglePubSub is UnitTest
  fun apply(h: TestHelper) =>
    h.long_test(2_000_000_000)

    ... // Produce and consume messages

    let p = Promise[USize]
    p.next[None]({(n: USize): None =>
      h.assert_eq[USize](2, n)
      h.complete(true) })
    c.get_number_consumed_messages(p)

h.long_test(请注意对and的额外调用h.complete,以及在测试结束时包装 lambda 的承诺。)

有关这些概念的更多信息,我建议您熟悉有关Promises的 stdlib 文档和Ponytest 的“长期测试”部分


推荐阅读