首页 > 解决方案 > 如何模拟其中一种结构方法?

问题描述

我有

type Service struct {
    config *config.Config
    model  *model.DB
    gates  *config.Gates
    rdb    *redis.Client
}

在哪里

type DB struct {
    *sql.DB
}

如何模拟其中一种结构方法?无需触及其他方法。

func (e *Service) FindGateErrorId(gate, errorCode, errorMessage string, eventObj model.EventObj) (string, error) {
if errorFormat, err := e.model.GetServiceParam(eventObj.ServiceId, "error_format", eventObj.IsTest); err != nil {
        return "", err
//some code
}

标签: unit-testinggo

解决方案


使要模拟的类型实现接口。然后,无论您在何处使用该类型,都将该类型的变量替换为该类型实现的接口的变量。现在可以交换实现该接口的任何类型。要模拟一种方法,而不是其他方法,用模拟包装非模拟类型。让 mock 中所有其他实现的方法简单地调用包装类型。对于您要模拟的方法,请实现您想要的逻辑。

type Animal interface {
    Say()
    Eat()
}

type Cat struct {}

func (c Cat) Say() {
    fmt.Println("meow")
}

func (c Cat) Eat() {
    fmt.Println("yum cat food meow")
}

type FunkyCatMock struct {
    wrapped Cat
}

func (m FunkyCatMock) Say() {
    fmt.Println("woof")
}

func (m FunkyCatMock) Eat() {
    m.wrapped.Eat()
}

func main() {
    var cat Animal
    var mock Animal

    cat = Cat{}

    mock = FunkyCatMock {
        wrapped: Cat{},
    }

    cat.Say()
    cat.Eat()
    mock.Say()
    mock.Eat()
}

要记住的另一件事是,如果您发现将许多方法放入一个接口中,您应该考虑如何将该接口分解为更小的接口。这将是更惯用的 Go。

例如:

type Writer interface {
    Write(p []byte) (n int, err error)
}

Go 使用的结构类型类似于鸭子类型,如果它看起来像一只鸭子并且它叫起来像一只鸭子,那么它一定是一只鸭子。

我提出这个问题的原因是,您可能会定义一个非常狭窄的接口,而不必担心模拟实现其他方法。


推荐阅读