猿问

扩展现有的类型 testing.T 以添加额外的检查

我意识到我可以将testing.T类型传递给需要处理测试接口的函数。但是如何扩展结构并使用它呢?我知道我可以输入扩展,但不幸的是这不起作用:


package test


import "testing"


type testingT testing.T


func (t *testingT) assert(val int) {

    if val == 0 {

        t.Errorf("%d is zero", val)

    }

}


func TestSomething(t *testingT) {

    t.assert(0)

}


牧羊人nacy
浏览 227回答 2
2回答

狐的传说

正如您在 eduncan911 的回答中所见,一种解决方案是嵌入。如果您想将其他字段添加到新结构中,那就太好了。但是,这不是必需的。创建一个新类型testing.T作为其底层类型(就像你所做的那样)就足够了:type myT testing.Tfunc (t *myT) assert(val int) {    if val == 0 {        t.Errorf("%d is zero", val)    }}使用它在TestSomething()我们不能只是调用t.assert(0)因为assert()不是方法testing.T而是我们的myT类型。所以我们需要一个myT可以调用的类型值myT.assert()。我们不能使用类型断言将 a 转换testing.T为我们的myT类型,因为类型断言要求表达式为接口类型!并且t不是接口类型,而是具体类型:*testing.T.解决方案非常简单,我们可以使用简单的类型转换,因为myT和testing.T具有相同的底层类型:my := myT(*t)   // Conversion valid, but not yet enough, read on...以上工作,我们可以调用:my.assert(0)但是在运行测试时,它不会失败!这是为什么?这是因为上面的*t解引用、转换和赋值会产生一个副本,并且my是类型myT但是会是的副本*t,所以当我们调用时myT.assert(),它得到一个指针,但是一个指向副本的指针。当myT.assert()调用 时t.Errorf(),它会在副本上注册错误,所以测试框架不会看到这个Errorf()调用。“最终”解决方案很简单:使用类型转换,但不转换*t,而是转换t本身(它是一个指针)。当然*t不能转换为myT,只能转换为*myT。并且这种类型需要用括号括起来(以避免歧义):func TestSomething(t *testing.T) {    my := (*myT)(t)    my.assert(0)}现在我们很高兴,一切都按预期进行。注意:myT.assert()如果不想调用多个方法,也可以在一行中调用myT:func TestSomething(t *testing.T) {    (*myT)(t).assert(0)}

蛊毒传说

您可以使用嵌入来添加所有者方法:package testimport "testing"type testingT struct {    *testing.T}func (t *testingT) assert(val int) {    if val == 0 {        t.Errorf("%d is zero", val)    }}func TestSomething(t *testing.T) {    t2 := &testingT{t}    t2.assert(0)}
随时随地看视频慕课网APP

相关分类

Go
我要回答