Meet Moq: Easily mock interfaces in Go
Meet Moq: Easily mock interfaces in Go
In my recent talk about Idiomatic Go Tricks I talked about a testing technique that David Hernandez showed me where you can test code that has dependencies (described by an interface) while keeping the mock code inside the test it belongs to.
You write a struct full of function fields that mirror the interface, and matching methods that just call those fields.
This allows you to write test code like this:
func TestCompleteSignup(t *testing.T) {
var sentTo string
// use the mocked object
mockedEmailSender = &EmailSenderMock{
SendFunc: func(to, subject, body string) error {
sentTo = to
return nil
},
}
CompleteSignUp("[email protected]", mockedEmailSender)
if len(mockedEmailSender.SendCalls()) != 1 {
t.Error("one Sender.Send expected")
}
if sentTo != "[email protected]" {
t.Errorf("unexpected recipient: %s", sentTo)
}
}
func CompleteSignUp(to string, sender EmailSender) {
// TODO: this
}
You mock out the functions in EmailSenderMock
that you expect to be called, and you can write throwaway custom behaviour for each specific test. You can see that the mocked functions are inside the test function itself, so it’s very clear to see what interactions with EmailSender
we’re expecting when we call the CompleteSignUp
method.
Inside the mocked functions, you can make assertions about what methods are being called, as well as decisions about what values to return. For example, you can decide to return an error, and make sure the code you are testing handles it properly.
The trouble with this technique is that there is a lot of boilerplate code to write each time you want to mock an interface. That’s where Moq comes in…
Introducing moq
Moq is a simple tool that writes these structs for you. You can visit the project homepage at github.com/matryer/moq.
How it works
Add the go:generate
comment above your interface:
package storage
//go:generate moq -out store_test.go . Store
type Store interface {
Get(id string) (interface{}, error)
Put(id string, v interface{}) error
}
- The
-out
flag indicates where the output should be saved to - The dot (
.
) indicates that the interface lives in the current package Store
indicates that we want to mock theStore
interface
Then run go generate
in a terminal and Moq will generate a new file called store_test.go
containing something like this:
package storage
type StoreMock struct {
// GetFunc mocks the Get function.
GetFunc func(id string) (interface{}, error)
// PutFunc mocks the Put function.
PutFunc func(id string, v interface{}) error
}
// Get calls GetFunc.
func (mock *StoreMock) Get(id string) (interface{}, error) {
return mock.GetFunc(id)
}
// Put calls PutFunc.
func (mock *StoreMock) Put(id string, v interface{}) error {
return mock.PutFunc(id, v)
}
This code is simplified — the actual generated code is slightly more sophisticated.
You can then use StoreMock
instances in your test code wherever you test code that relies on a Store
.
You can install Moq and use it today with:
go get github.com/matryer/moq
As usual, feedback and questions are welcome on Twitter @matryer.
相關推薦
Meet Moq: Easily mock interfaces in Go
Meet Moq: Easily mock interfaces in GoMoq is an Interface mocking tool for go generate — github.com/matryer/moqIn my recent talk about Idiomatic Go Tricks
Yet another tool to mock interfaces in Go
Yet another tool to mock interfaces in Go https://itnext.io/yet-another-tool-to-mock-interfaces-in-go-73de1b02c041 As a powerful tool, uni
A GIF decoder: an exercise in Go interfaces
25 May 2011 Introduction At the Google I/O conference in San Francisco on May 10, 2011, we announced that the Go
理解golang反射(reflection in Go)
golang reflect golang反射 go反射機制 反射(reflection)是指在運行時,動態獲取程序結構信息(元信息)的一種能力,是靜態類型語言都支持的一種特性,如Java, golang等。這裏主要詳細介紹golang reflection相關知識類型與接口(Types and
Context propagation over HTTP in Go
https://medium.com/@rakyll/context-propagation-over-http-in-go-d4540996e9b0 Context propagation over HTTP in Go Go 1.7 introduced a built-in
Downloading large files in Go
package main import ( "fmt" "github.com/cavaliercoder/grab" "time" ) func download(dst string,urls ...string) { n:=len(urls) re,err:=grab.Get
How I organize my applications in Go[轉]
Overview For me, the hardest part of learning Go was in structuring my application. Prior to Go, I was working on a Rails applicat
Building an Excellent Mock Server in Swift using Vapor
What is a Mock Server?Before explaining what a mock server is, we’ll start with what a mock is and why you might use one. I’ll also avoid delving into the
Variadic function in Go
What is a variadic function?As we have seen in a functions lesson, a function is a piece of code dedicated to do a particular job. A function takes one or
How big is an int in Go?
How big is an int in Go?Go has several built-in numeric types, “sets of integer or floating-point values.” Some architecture-independent types are uint8 (8
5 advanced testing techniques in Go · Segment Blog
Go has a robust built-in testing library. If you write Go, you already know this. In this post we will discuss a handful of strategies to level up your G
Using Parser Combinators in Go
Using Parser Combinators in GoLet’s parse in Golang!How would you write a parser for the following calculator grammar?Digit := "0" | "1" | "2" | "3" | "4"
This Blogpost Deploys Servers in Go, NodeJS, Ruby, Python, Java, PHP
This Blogpost Deploys Servers in Go, NodeJS, Ruby, Python, Java, PHPRunning the embeded Repl.it code in this post will live-deploy simple http servers for
Tinyterm: A silly terminal emulator written in Go
This post is about Tinyterm, a silly hack that I presented as a lightning talk at last month’s Sydney Go User group 1. You can find the original slide
Bit manipulation in Go
Bit manipulation is important to know when doing data compression, cryptography and optimization. Bitwise operations include AND, NOT, OR, XOR and bit s
String manipulation in Go
Basic Operations Get char array of a String greeting := "Comment allez-vous" greeingCharacterArr := []rune(greeting) Get a char at the specific i
Based User Interfaces · Applied Go
Console applications usually take some parameters at start, and maybe some more input through basic console I/O. And that’s ok in most cases, though som
Processing spreadsheet data in Go · Applied Go
This article is also available as a video on the Applied Go YouTube channel: It is the shortened version of a lecture in my upcoming minicourse “
Scheduling In Go
IntroductionThe design and behavior of the Go scheduler allows your multithreaded Go programs to be more efficient and performant. This is thanks to the me
Bounds Check Elimination In Go
IntroductionOne day I was talking to Damian Gryski in Slack about some performance improvements he made to his go-metro package. When I first looked at the