在 go 中测试非返回方法

Kar*_*rks 4 testing go

我有一个简单的方法,它只检查参数是否为空,然后根据结构字段调用 2 个方法之一。
我将如何测试它?

func (cT *customType) someMethod(message string) {
    if message == ""{
        return
    }

    if cT.value == nil {
        cT.doFunctionOne()
    } else {
        cT.doFunctionTwo()
    }
}
Run Code Online (Sandbox Code Playgroud)

在 Javascript 中,我会创建一个监视对象doFunctionOne()并模拟该对象。
模拟Go也很有效,但是我该如何做“间谍”部分呢?
或者还有另一种惯用的方法来测试这种方法吗?

Alv*_*ivi 5

在 Go 中模拟对象的惯用方法是使其显式化。一个健康的界面应该是可自行测试的。所以如果我们有这样的东西:

type customType struct {
    value int
}

func (c customType) doFunctionOne() {
    fmt.Println("Method #1")
}

func (c customType) doFunctionTwo() {
    fmt.Println("Method #2")
}

func (c customType) someMethod() {
    if c.value <= 0 {
        c.doFunctionOne()
    } else {
        c.doFunctionTwo()
    }
}
Run Code Online (Sandbox Code Playgroud)

我们必须提供一种方法来显式地改变doFunctionOne和的实现doFunctionTwo。我们可以someMethod使用接口来概括行为:

type customType struct {
    myValue int
}

func (c customType) doFunctionOne() {
    fmt.Println("Method #1")
}

func (c customType) doFunctionTwo() {
    fmt.Println("Method #2")
}

func (c customType) value() int {
    return c.myValue
}

type Interface interface {
    value() int
    doFunctionOne()
    doFunctionTwo()
}

func someMethod(i Interface) {
    if i.value() <= 0 {
        i.doFunctionOne()
    } else {
        i.doFunctionTwo()
    }
}

type customTestingType struct {
    t *testing.T
}

func (c customTestingType) doFunctionOne() {
    c.t.Log("Working")
}

func (c customTestingType) doFunctionTwo() {
    c.t.Error("Not working")
}

func (c customTestingType) value() int {
    return 0
}

func TestInterface(t *testing.T) {
    someMethod(customTestingType{t})
}
Run Code Online (Sandbox Code Playgroud)

当然会有更多的方法来提供这种行为,但这取决于您的类型的特定声明。作为示例,您可以查看 httptestpackage.json。也就是说,如果你真的想以这种方式模拟你的类型(非惯用),你可以进行一些不安全的猴子修补

package main

import (
    "fmt"
    "reflect"

    "github.com/bouk/monkey"
)

type customType struct {
    myValue int
}

func (c customType) doFunctionOne() {
    fmt.Println("Method #1")
}

func (c customType) doFunctionTwo() {
    fmt.Println("Method #2")
}

func (c customType) someMethod() {
    if c.myValue <= 0 {
        c.doFunctionOne()
    } else {
        c.doFunctionTwo()
    }
}

func main() {
    c := customType{0}
    monkey.PatchInstanceMethod(reflect.TypeOf(c), "doFunctionOne",
        func(c customType) {
            fmt.Println("Method #1, but patched")
        })
    monkey.PatchInstanceMethod(reflect.TypeOf(c), "doFunctionTwo",
        func(c customType) {
            fmt.Println("Method #2, but patched")
        })
    c.someMethod()
}
Run Code Online (Sandbox Code Playgroud)