用于测试的golang接口

mklgxw1f  于 2023-02-10  发布在  Go
关注(0)|答案(2)|浏览(155)

我尝试在我的代码中创建一个数据库mock,然后我在代码中引入接口来创建mock:
这是我的代码(我不知道这是不是正确的方法)

package interfaces

type ObjectAPI interface {
    FindSomethingInDatabase(ctx context.Context, name string) (e.Response, error)
}

我的接口实现是:

package repositories

func FindSomethingInDatabase(ctx context.Context, name string) (e.Response, error) {

    statement, err := db.SqlStatementWithCtx(ctx,
        `SELECT * 
         FROM table
         WHERE name = ? LIMIT 1`)

    row := statement.QueryRowContext(ctx, name)

    if err != nil {
        return e.Response{}, err
    }

    statement.Close()
    return toResponse(row), nil  //this method convert row database to e.Response struct

}

现在我需要从一个方法调用FindSomethingInDatabase的实现,然后我会收到一个对象类型接口:

func CallImplementation(request *dto.XRequest, repo i.ObjectAPI) dto.XResponse{
    result := repo.FindSomethingInDatabase(request.Ctx, request.Name)
// more code
}

但是现在我不知道如何调用CallImplementation '来传递一个对象。
调用传递接口实现的方法

bcs8qyzn

bcs8qyzn1#

一个接口描述一个 type。因为你的FindSomethingInDatabase实现只是一个没有接收器的函数,所以没有类型实现接口ObjectAPI
您可以将func(ctx context.Context, name string) (e.Response, error)类型的值作为回调传递到CallImplementation,并完全摆脱接口。或者,保留接口,定义一个类型,并使该类型成为当前FindSomethingInDatabase实现的接收方。然后,您可以将该类型传递到CallImplementation。因为它现在将实现ObjectAPI接口。后者的一个示例(这将是我的首选扩展选项):

type database struct {}

func (d *database) FindSomethingInDatabase(ctx context.Context, name string) (e.Response, error) {
    // ...
}

func CallImplementation(request *dto.XRequest, repo i.ObjectAPI) dto.XResponse{
    result := repo.FindSomethingInDatabase(request.Ctx, request.Name)
// more code
}

func main() {
    db := &database{}
    _ = Callimplementation(getRequest(), db)
}

在这种情况下,您可能希望将db存储为database的成员,而不是将其存储为全局变量(现在似乎就是这种情况)。

a2mppw5e

a2mppw5e2#

参考mockery。它提供了接口模拟的自动生成,并且可以作为模拟最佳实践的良好参考。
通常您会这样做:
api.go:

type API interface {
    Something(ctx context.Context, name string) (e.Response, error)
}

type ApiImpl struct {
  
}

func (t *ApiImpl) Something(ctx context.Context, name string) (e.Response, error) {
    // impl
}

API_测试.go

// mocks can be hand coded or autogenerated using mockery
type MockImpl struct {
}

func (m *MockImpl) Something(ctx context.Context, name string) (e.Response, error) {
    // mock implementation
}

func TestSomething(t * testing.T) {
    // test code with mocks
}

相关问题