简体   繁体   English

在 GO lang 中模拟

[英]Mocking in GO lang

I am new to Go and I am still trying to get my head around its concept.我是Go 的新手,我仍在努力理解它的概念。 I am trying to create a simple unit test and want to Mock one of its service.我正在尝试创建一个简单的单元测试并想Mock它的一项服务。 I want to mock my_mod_2.EmpInfo in it so that I dont call the actual service.我想在其中模拟my_mod_2.EmpInfo ,这样我就不会调用实际的服务。

method-1.go方法 1.go

package my_mod_1

import (
    "awesomeProject-1/my-mod-2"
)

func CreateAndSendMail() string {
    svc := my_mod_2.EmpInfo{}
    name := svc.GetName()
    empAddress := svc.GetAddress()
    return name + " lives in " + empAddress
}

Here is Emp.go这里是Emp.go

package my_mod_2

import "fmt"

type EmpInfo struct {}

func (o EmpInfo) GetName()  string{
    fmt.Println("Called actual")
    return "John Doe"
}

func (o EmpInfo) GetAddress() string {
    return "US"
}

Here is the method-1_test.go这是方法-1_test.go

package my_mod_1

import (
    "testing"
)

func TestCreateAndSendMail(t *testing.T) {
    val := CreateAndSendMail()
    if val != "John Doe lives in US" {
        t.Error("Value not matched")
    }
}

I am seeing Called actual in test execution.我在测试执行中看到Called actual I Know I have to create a mock using interface but I am just not getting it.我知道我必须使用interface创建一个模拟,但我只是没有得到它。 Can someone please help me out with this small code ?有人可以帮我解决这个小代码吗?

First of all, you need to prepare your code to use interfaces and mocks.首先,您需要准备代码以使用接口和模拟。 To do this I suggest you to declare Service interface beside CreateAndSendMail method.为此,我建议您在CreateAndSendMail方法旁边声明Service接口。 In this case, it is better to pass service instance to the method or use it as an instance variable of a struct to which your method is belong:在这种情况下,最好将服务实例传递给方法或将其用作方法所属结构的实例变量:

type Service interface {
    GetName() string
    GetAddress() string
}

func CreateAndSendMail(svc Service) string {
    name := svc.GetName()
    empAddress := svc.GetAddress()
    return name + " lives in " + empAddress
}

or或者

type Service interface {
    GetName() string
    GetAddress() string
}

type S struct {
    svc Service
}

func (s *S) CreateAndSendMail() string {
    name := s.svc.GetName()
    empAddress := s.svc.GetAddress()
    return name + " lives in " + empAddress
}

Then, your EmpInfo will implement your Service interface implicitly.然后,您的EmpInfo将隐式实现您的Service接口。 And this is a cool feature of golang interfaces.这是 golang 接口的一个很酷的特性。 After all our preparations, we are ready to create test.一切准备就绪后,我们就可以开始创建测试了。 To do this, we can implement mocks by ourselves:为此,我们可以自己实现模拟:

import (
    "testing"
)

type MockSvc struct {
}

func (s *MockSvc) GetName() string {
    return "Mocked name"
}

func (s *MockSvc) GetAddress() string {
    return "Mocked address"
}

func TestCreateAndSendMail(t *testing.T) {
    svc := &MockSvc{}

    val := CreateAndSendMail(svc)
    if val != "Mocked name lives in Mocked address" {
        t.Error("Value not matched")
    }
}

Also, we can use special tool gomock to automate mock creation process此外,我们可以使用特殊工具gomock来自动化模拟创建过程

Interfaces are the most used Go features that helps with testing.接口是最常用的有助于测试的 Go 特性。 Interface in Go allows for Duck Typing where you can switch any type that has implemented an interface to be mocked by a different type. Go 中的接口允许 Duck Typing,您可以在其中切换已实现接口的任何类型以由不同类型模拟。

From your example, the service has the following two methods: GetName() and GetAddress().在您的示例中,该服务具有以下两种方法:GetName() 和 GetAddress()。 Create an interface Service with these two methods.使用这两种方法创建一个接口 Service。

type Service Interface {
    GetName() string
    GetAddress() string
}

Now your struct EmpInfo, already implements the Service interface.现在您的结构 EmpInfo,已经实现了 Service 接口。 Create a new MockService struct with same 2 functions.使用相同的 2 个函数创建一个新的 MockService 结构。

type MockService struct {}

func (ms *MockService) GetName() string {
// Mock Code
}

func (ms *MockService) GetAddress() string {
// Mock Code
}

Then, replaces instances of EmpInfo with MockService wherever you need.然后,在需要的地方用 MockService 替换 EmpInfo 的实例。

PS: Consider adding functions GetName and GetAddress with pointer to EmpInfo. PS:考虑添加带有指向 EmpInfo 的指针的函数 GetName 和 GetAddress。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM