猿问

验证模拟调用的顺序

我使用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

}


繁星淼淼
浏览 136回答 3
3回答

慕妹3242003

这不是直接支持的,即使有一个未解决的问题(stretchr/testify/issue 741 "assert mock calls in order")更一般的问题684“断言调用顺序?” 包括反驳:IMO 你应该检查函数的输出,而不是它在内部是如何工作的。它可能会导致很难维护的测试实现。虽然,在同一个线程中:IMO 有强制执行命令的情况。即如果你模拟一个互斥锁,你最好检查在解锁之前总是调用锁。我们可以有一个简单的实现,其中模拟有一个“ assertExpectationsInOrder”真/假标志,可以在添加任何期望之前设置。这可能会导致一些测试,例如cassandra-operator/cmd/operator/controller_test.go哪些记录事件来测试他们的订单。

蝴蝶刀刀

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如果有原因,您可以使订单检查逻辑复杂化......

呼唤远方

正如其他人所说,这是一个内部细节,并且确实将您的测试与实现纠缠在一起。如果您确定订单很重要,这将毫无意义。在这里保持简洁是另一种使用最低限度测试订单的解决方案。创建两个实现 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()        }    }}
随时随地看视频慕课网APP

相关分类

Go
我要回答