扩展现有型式试验.T 表示添加额外检查

  • 本文关键字:添加 表示 扩展 testing go
  • 更新时间 :
  • 英文 :


我意识到我可以将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)
}

一种解决方案是嵌入,正如您在 eduncan911 的答案中看到的那样。如果要将其他字段添加到新结构中,那就太好了。

但是,这不是必需的。创建一个以 testing.T 作为其基础类型的新类型(就像您所做的那样(就足够了:

type myT testing.T
func (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() .

但是,我们不能使用类型断言将testing.T转换为我们的myT类型,因为类型断言要求表达式为接口类型!t不是接口类型,而是具体类型:*testing.T

解决方案非常简单,我们可以使用简单的类型转换,因为myTtesting.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方法,也可以在一行中调用myT.assert()

func TestSomething(t *testing.T) {
    (*myT)(t).assert(0)
}

您可以使用嵌入来添加所有者方法:

package test
import "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)
}

准备自定义测试结构:

type T testing.T
func (t *T) AssertEqualsInt(expected, actual int) {
    if actual != expected {
        // Correct point for file and line where happened error
        t.Helper()
        t.Errorf("Values not equal expected: %d, got: %d", expected, actual)
    }
}
func (t *T) AssertEqualsString(expected, actual string) {
    if actual != expected {
        t.Helper()
        t.Errorf("Values not equal expected: %s, got: %s", expected, actual)
    }
}

比在测试中使用它:

func TestFooBarBaz(t *testing.T) {
    (*T)(t).AssertEqualsInt(0, 10)
    (*T)(t).AssertEqualsString("foo", "bar")
}

最新更新