Mock Test with Gomock

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

In the development process often need to cooperate with unit testing, but many times, unit testing needs to rely on some more complex preparations, such as the need to rely on the database environment, the need to rely on the network environment, unit testing has become a very troublesome thing. For example, for example, we need to request a Web page and process the requested data back. At first, I usually start a simple HTTP service before running my unit tests. But this unit test seems to be very cumbersome to measure. Even during the continuous integration process, I wrote a script to automatically start the corresponding service in order to be able to automate the test. Things seem to need some change.

The mock object is born to solve the problem above, the mock (mock) object can simulate the function of the actual dependent object, without the need of very complicated preparation, all you need to do is define the object interface, then implement it, then give it to the test object to use.

Go-mock is a mock library specially developed for go language, which is simple to use and supports automatic generation of code, which can be said to be a rare and good tool. Let me briefly show you how Go-mock works:

The first thing you need to do is to download the dependencies locally:

go get github.com/golang/mock/gomockgo get github.com/golang/mock/mockgen

The first is code-dependent, and the second is the command-line tool (especially useful).

Here's a very simple example to illustrate how Gomock works:

I'm $GOPATH/src creating a new project under the directory: hellomock create a new one in the $GOPATH/src/hellomock directory hellomock.go , and define an interface Talker :

package hellomocktype Talker interface {    SayHello(word string)(response string)}

Then we need a Talker struct that implements the function, assuming that we have a scene where we now have a welcome post and a welcome receptionist, and of course the usher can be a person or a parrot. So what we need to do is define a Persion struct (or a parrot or something else) and implement the Talker interface:

person.go

package hellomockimport "fmt"type Person struct{  name string}func NewPerson(name string)*Person{  return &Person{      name:name,  }}func (p *Person)SayHello(name string)(word string) {  return fmt.Sprintf("Hello %s, welcome come to our company, my name is %s",name,p.name)    }

Now that we Person have implemented the Talker interface, let's make him work now!

Now suppose we have a company that has a receptionist, the sister of our front desk, who implements the Talker interface. She was able to automatically always be the guest SayHello :

company.go

package hellomocktype Company struct {  Usher Talker}func NewCompany(t Talker) *Company{  return &Company{    Usher:t,  }}func ( c Company) Meeting(gusetName string)string{  return c.Usher.SayHello(gusetName)}

Our scene has been designed, so how do we implement unit testing in the traditional way?

company_test.go

package hellomockimport "testing"func TestCompany_Meeting(t *testing.T) {    person := NewPerson("王尼美")    company := NewCompany(person)    t.Log(company.Meeting("王尼玛"))}

Test:

/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting$    company_test.go:8: Hello 王尼玛, welcome come to our company, my name is 王尼美ok      hellomock    0.013s

Now we're building a 王尼美 simple one, but now we're going to simulate with mock objects, and we're mockgen on the scene:

➜  hellomock> mkdir mock                                        ➜  hellomock> mockgen -source=hellomock.go > mock/mock_Talker.go

This time, the file will be generated mock/mock_Talker.go :

It is important to note that automatically generated files with the same source file under different packages, you need to create a new directory to store

We don't need to care about the content of the generated file, we just need to know how to use it.

mock_Talker.go

Automatically generated by Mockgen. Do not edit!//Source:hellomock.gopackage mock_hellomockimport (gomock "Github.com/golang/mock/gomock")//Mocktalker is a mock of Talker interfacetype mocktalker struct {Ctrl *gomock. Controller Recorder *mocktalkermockrecorder}//Mocktalkermockrecorder is the mock recorder for Mocktalkertype Mocktalke Rmockrecorder struct {Mock *mocktalker}//newmocktalker creates a new mock Instancefunc newmocktalker (Ctrl *gomock. Controller) *mocktalker {mock: = &mocktalker{ctrl:ctrl} mock.recorder = &mocktalkermockrecorder{mock} r Eturn mock}//EXPECT Returns an object it allows the caller to indicate expected Usefunc (_m *mocktalker) EXPECT () *mock  Talkermockrecorder {return _m.recorder}//SayHello mocks base methodfunc (_m *mocktalker) SayHello (name string) string {ret: = _m.ctrl.call (_m, "SayHello", name) Ret0, _: = Ret[0]. (string) return ret0}//SayHello indicates an expected call of Sayhellofunc (_MR *mockTalkermockrecorder) SayHello (arg0 interface{}) *gomock. Call {return _mr.mock.ctrl.recordcall (_mr.mock, "SayHello", arg0)}

Next look at how to use this mock object and create a new unit test:

func TestCompany_Meeting2(t *testing.T) {    ctl := gomock.NewController(t)    mock_talker := mock_hellomock.NewMockTalker(ctl)    mock_talker.EXPECT().SayHello(gomock.Eq("王尼玛")).Return("这是自定义的返回值,可以是任意类型。")    company := NewCompany(mock_talker)    t.Log(company.Meeting("王尼玛"))    //t.Log(company.Meeting("张全蛋"))}

Test:

/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting2$    company_test.go:21: 这是自定义的返回值,可以是任意类型。ok      hellomock    0.015s

As you can see, the return value we defined on the mock object is returned.

One point to note is that the acceptable parameters of the mock object SayHello are gomock.Eq(x interface{}) the gomock.Any() same as, the previous requirement that the test case is in strict compliance with the meal, and the x second allows any arguments to be passed in. For example, we passed the "Zhangquan egg" in the commented out test, the result is error, the test failed:

/usr/local/go/bin/go test -v hellomock -run ^TestCompany_Meeting2$    controller.go:113: no matching expected call: *mock_hellomock.MockTalker.SayHello([张全蛋])exit status 1FAIL    hellomock    0.007s

This article as a gomock, there are many high-level usage, I hope you can explore on their own.

Reference article:

Https://github.com/golang/moc ...

Https://github.com/grpc/grpc-...

Reprint please specify the source http://www.chenquan.me

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.