如何仅模拟接口的一种方法

时间:2019-07-05 17:49:59

标签: unit-testing go mocking testify gomock

我正在努力理解Go中的模拟(正在寻找与Go中Java的Mockito.spy等效的东西)。

假设我在Go中有5种方法的接口。但是我要测试的代码仅引用了两种方法。现在我该如何在不实现所有方法的情况下模拟此依赖关系,即我在源代码中的实际实现实现了接口的5种方法,但是有一种方法可以避免在测试文件中实现5种方法的虚拟接口实现。以下是当前的操作方式,实现5种方法是可管理的,但是如果接口有20种方法,在测试文件中模拟实现所有方法将变得很乏味。

示例:

handler.go中的源代码:

type Client struct {}
type ClientStore interface {
  func(c *Client) methodOne() error {// some implementation}
  func(c *Client) methodTwo() error {// some implementation}
  func(c *Client) methodThree() error {// some implementation}
  func(c *Client) methodFour() error {// some implementation}
  func(c *Client) methodFive() error {// some implementation}
}

api.go中的源代码:

 func processFeed(c Client) error {
     err := c.methodOne()
     if(err != null) {
      return err
    }
     err1 := c.methodTwo()
     if(err1 != null) {
      return err1
    }
 }

测试类代码:

import "testify/mock"

func TestFeed(t *testing.T){
   mockClient := &MockClient{}
   err := processFeed(mockClient)
   assert.NotNil(t , err)

}

type MockClient struct {
  mock.Mock
}

  func(c *MockClient ) methodOne() error {fmt.Printf("methodOne");nil}
  func(c *MockClient ) methodTwo() error {return errors.New("mocked error")}
  func(c *MockClient ) methodThree() error {fmt.Printf("methodThree");nil}
  func(c *MockClient ) methodFour() error {fmt.Printf("methodFour");nil}
  func(c *MockClient ) methodFive() error {fmt.Printf("methodFive");nil}


问题:

有没有一种方法可以只模拟我在上述情况下只需要methodOne()和methodTwo()方法,而不必担心测试中剩余的方法?如果可以的话,您能提出其他建议吗?谢谢

1 个答案:

答案 0 :(得分:3)

首先,如果您的界面有5种方法,而您仅使用一种方法,则您的界面太大。使用较小的界面。

type BigInterface interface {
    Thing1()
    Thing2()
    ThingN()
}

type SmallInterface interface {
    Thing1()
}

func MyFunc(i SmallInterface) { ... }

另一种选择是通过嵌入完整接口来创建完整接口的完整实现。如果您尝试访问其他方法之一,这将引起恐慌,但是如果您小心一点,则可以进行测试。 (但是请不要在生产代码中执行此操作!)

type BigInterface interface {
    Thing1()
    Thing2()
    ThingN()
}

type myImplementation struct {
    BigInterface
}

func (i *myImplementation) Thing1() { ... }

现在,myImplementation通过包含BigInterface的嵌入式实例而满足BigInterface接口。如果您从未将该嵌入式实例设置为任何实例,则调用这些方法会感到恐慌,但是您仍然可以定义Thing1来执行您想要的测试。