首页 > 解决方案 > 如何使用相互依赖的接口方法模拟结构

问题描述

我在 Go 中为一个相当常见的用例/模式编写单元测试时遇到了麻烦。

想象一下,如果你愿意的话,是这样的:

package main

type Resource struct {
    name string
}

type ResourceManager interface {
    GetResource(id string) (*Resource, error)
    GetAllResources() ([]*Resource, error)
}

type ResourceManagerImpl struct {
}

func (r *ResourceManagerImpl) GetResource(id string) (*Resource, error) {
    resource := &Resource{}
    var err error

    // fetch resource.
    // ...

    return resource,  err
}

func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
    var resources []*Resource
    var err error

    // for _, id := range ids {
    //  resource = r.GetResource(id)
    //  resources = append(resources, resource)
    // }

    return resources, err
}

根据需要重复调​​用GetAllResources是一种常见的模式。GetResource

我可以使用gomockortestify来测试GetResource. 但是,在测试时GetAllResource,我想模拟GetResource. 否则,测试将成为一场噩梦。这就是在 Java 中easymockmockito在使用部分模拟的情况下的方式。但是,尚不清楚如何在 Golang 中实现相同的目标。

具体来说,我找不到如何部分模拟struct. 大多数建议都围绕着打破这样struct的 s 但在这种情况下,这struct已经是最低限度了。为了测试而不要将接口(分为单个和多个)打破似乎是一个公平的要求,ResourceManager因为这没有多大意义,而且充其量也是笨拙的,并且随着更多这样的方法进入接口,也不能很好地扩展。

标签: unit-testinggotestingmockinggo-interface

解决方案


这就是我处理这种情况的方式:

func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
   return getAllResources(r)
}


func getAllResources(r ResourceManager) ([]*Resource,error) {
  ...
}

然后你测试getAllResources而不是GetAllResources使用模拟的r. 如果您遇到从代码调用的情况GetAllResources并且您必须 mock GetAllResources,您可以执行以下操作:

var getAllResources=func(r ResourceManager) ([]*Resource,error) {
...
}

并将 getAllResources 分配给一个测试实例。


推荐阅读