为了账号安全,请及时绑定邮箱和手机立即绑定

验证模拟调用的顺序

验证模拟调用的顺序

Go
繁星淼淼 2022-06-21 16:20:58
我使用testify(v1.6.1)并且需要测试接口的方法是否以正确的顺序调用。我检查了文档并试图在互联网上找到任何信息,但没有找到任何关于模拟订单检查的信息。例子:type InterfaceA interface {    Execute()}type InterfaceB interface {    Execute()}type Composition struct {    a InterfaceA    b InterfaceB}func (c * Composition) Apply() error {    //How to check that "a" execute before "b"?    c.a.Execute()    c.b.Execute()    return nil}
查看完整描述

3 回答

?
慕妹3242003

TA贡献1824条经验 获得超6个赞

这不是直接支持的,即使有一个未解决的问题(stretchr/testify/issue 741 "assert mock calls in order"

更一般的问题684“断言调用顺序?” 包括反驳:

IMO 你应该检查函数的输出,而不是它在内部是如何工作的。它可能会导致很难维护的测试实现。

虽然,在同一个线程中:

IMO 有强制执行命令的情况。即如果你模拟一个互斥锁,你最好检查在解锁之前总是调用锁。
我们可以有一个简单的实现,其中模拟有一个“ assertExpectationsInOrder”真/假标志,可以在添加任何期望之前设置。

这可能会导致一些测试,例如cassandra-operator/cmd/operator/controller_test.go哪些记录事件来测试他们的订单。


查看完整回答
反对 回复 2022-06-21
?
蝴蝶刀刀

TA贡献1801条经验 获得超8个赞

IMO 有强制执行命令的情况。即如果你模拟一个互斥锁,你最好检查在解锁之前总是调用锁。


这是一个简单的单线程实现:


func TestOrderOfMocks(t *testing.T) {

    order := 0

    amock := new(AMock)

    amock.On("Execute").Run(func(args mock.Arguments) {

        if order++; order != 1 {

            t.Fail()

        }

    })


    bmock := new(BMock)

    bmock.On("Execute").Run(func(args mock.Arguments) {

        if order++; order != 2 {

            t.Fail()

        }

    })


    c := &Composition{amock, bmock}

    err := c.Apply()

    require.NoError(t, err)

}

PLAYGROUND


如果有原因,您可以使订单检查逻辑复杂化......


查看完整回答
反对 回复 2022-06-21
?
呼唤远方

TA贡献1856条经验 获得超11个赞

正如其他人所说,这是一个内部细节,并且确实将您的测试与实现纠缠在一起。如果您确定订单很重要,这将毫无意义。在这里保持简洁是另一种使用最低限度测试订单的解决方案。


创建两个实现 InterfaceA 和 InterfaceB 的间谍。


type SpyA struct {

    Calls *[]string

}


func (s *SpyA) Execute() {

    *s.Calls = append(*s.Calls, "ExecuteA")

}


type SpyB struct {

    Calls *[]string

}


func (s *SpyB) Execute() {

    *s.Calls = append(*s.Calls, "ExecuteB")

}

然后像这样使用它们。


func TestApply(t *testing.T) {

    got := []string{}

    c := &Composition{

        a: &SpyA{&got},

        b: &SpyB{&got},

    }


    c.Apply()


    expected := []string{"ExecuteA", "ExecuteB"}


    if len(got) != len(expected) {

        t.Fail()

    }


    for i := range got {

        if got[i] != expected[i] {

            t.Fail()

        }

    }

}


查看完整回答
反对 回复 2022-06-21
  • 3 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信