Mock functions in Go

golang mock private function
go mock server
golang mock tutorial
golang mock implementation
golang intercept function call
golang/mock external api
golang unit test mock database
wiremock golang

I'm learning Go by coding a small personal project. Even though it's small, I decided to do rigorous unit testing to learn good habits on Go right from the start.

Trivial unit tests were all fine and dandy, but I'm puzzled with dependencies now; I want to be able to replace some function calls with mock ones. Here's a snippet of my code:

func get_page(url string) string {
    get_dl_slot(url)
    defer free_dl_slot(url)

    resp, err := http.Get(url)
    if err != nil { return "" }
    defer resp.Body.Close()

    contents, err := ioutil.ReadAll(resp.Body)
    if err != nil { return "" }
    return string(contents)
}

func downloader() {
    dl_slots = make(chan bool, DL_SLOT_AMOUNT) // Init the download slot semaphore
    content := get_page(BASE_URL)
    links_regexp := regexp.MustCompile(LIST_LINK_REGEXP)
    matches := links_regexp.FindAllStringSubmatch(content, -1)
    for _, match := range matches{
        go serie_dl(match[1], match[2])
    }
}

I'd like to be able to test downloader() without actually getting a page through http - i.e. by mocking either get_page (easier since it returns just the page content as a string) or http.Get().

I found this thread: https://groups.google.com/forum/#!topic/golang-nuts/6AN1E2CJOxI which seems to be about a similar problem. Julian Phillips presents his library, Withmock (http://github.com/qur/withmock) as a solution, but I'm unable to get it to work. Here's the relevant parts of my testing code, which is largely cargo cult code to me, to be honest:

import (
    "testing"
    "net/http" // mock
    "code.google.com/p/gomock"
)
...
func TestDownloader (t *testing.T) {
    ctrl := gomock.NewController()
    defer ctrl.Finish()
    http.MOCK().SetController(ctrl)
    http.EXPECT().Get(BASE_URL)
    downloader()
    // The rest to be written
}

The test output is following:

ERROR: Failed to install '_et/http': exit status 1
output:
can't load package: package _et/http: found packages http (chunked.go) and main (main_mock.go) in /var/folders/z9/ql_yn5h550s6shtb9c5sggj40000gn/T/withmock570825607/path/src/_et/http

Is the Withmock a solution to my testing problem? What should I do to get it to work?


Kudos to you for practicing good testing! :)

Personally, I don't use gomock (or any mocking framework for that matter; mocking in Go is very easy without it). I would either pass a dependency to the downloader() function as a parameter, or I would make downloader() a method on a type, and the type can hold the get_page dependency:

Method 1: Pass get_page() as a parameter of downloader()
type PageGetter func(url string) string

func downloader(pageGetterFunc PageGetter) {
    // ...
    content := pageGetterFunc(BASE_URL)
    // ...
}

Main:

func get_page(url string) string { /* ... */ }

func main() {
    downloader(get_page)
}

Test:

func mock_get_page(url string) string {
    // mock your 'get_page()' function here
}

func TestDownloader(t *testing.T) {
    downloader(mock_get_page)
}
Method2: Make download() a method of a type Downloader:

If you don't want to pass the dependency as a parameter, you could also make get_page() a member of a type, and make download() a method of that type, which can then use get_page:

type PageGetter func(url string) string

type Downloader struct {
    get_page PageGetter
}

func NewDownloader(pg PageGetter) *Downloader {
    return &Downloader{get_page: pg}
}

func (d *Downloader) download() {
    //...
    content := d.get_page(BASE_URL)
    //...
}

Main:

func get_page(url string) string { /* ... */ }

func main() {
    d := NewDownloader(get_page)
    d.download()
}

Test:

func mock_get_page(url string) string {
    // mock your 'get_page()' function here
}

func TestDownloader() {
    d := NewDownloader(mock_get_page)
    d.download()
}

How to mock? Go Way., Go has a built-in testing framework provided by the testing package, that Mock implementation is returning an userExistsMock function type  Step by Step Step 1: Define Request and Response. As usual, create structs to handle request and response. Step 2: Define an Interface. Create an interface to get rates and another struct to implement the interface. Step 3: Create a Unit Test for getRates Function. For this unit testing, I will


If you change your function definition to use a variable instead:

var get_page = func(url string) string {
    ...
}

You can override it in your tests:

func TestDownloader(t *testing.T) {
    get_page = func(url string) string {
        if url != "expected" {
            t.Fatal("good message")
        }
        return "something"
    }
    downloader()
}

Careful though, your other tests might fail if they test the functionality of the function you override!

The Go authors use this pattern in the Go standard library to insert test hooks into code to make things easier to test:

https://golang.org/src/net/hook.go

https://golang.org/src/net/dial.go#L248

https://golang.org/src/net/dial_test.go#L701

Mocking Methods in Go - DEV, Mocking in golang is done with the help of interfaces. Mocking in unit testing is important as it ensure that variables, methods and functions  How to mock?Go Way. System. Example System and Integration. Our system has two components. Now Since we are building “Our Service” we want Third-party Library Code. Service. Registers a user. It uses a third party to check for the user’s existence. If the user exists, the service Mocks. Let’s


Mocking functions in Go · npf.io, Mocking functions in Go. Apr 10, 2014. Functions in Go are first class citizens, that means you can have a variable that contains a function value, and call it like a  Mock Functions Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with new, and allowing test-time configuration of return values.


I would do something like,

Main

var getPage = get_page
func get_page (...

func downloader() {
    dl_slots = make(chan bool, DL_SLOT_AMOUNT) // Init the download slot semaphore
    content := getPage(BASE_URL)
    links_regexp := regexp.MustCompile(LIST_LINK_REGEXP)
    matches := links_regexp.FindAllStringSubmatch(content, -1)
    for _, match := range matches{
        go serie_dl(match[1], match[2])
    }
}

Test

func TestDownloader (t *testing.T) {
    origGetPage := getPage
    getPage = mock_get_page
    defer func() {getPage = origGatePage}()
    // The rest to be written
}

// define mock_get_page and rest of the codes
func mock_get_page (....

And I would avoid _ in golang. Better use camelCase

Mocking, Go itself already shipped with testing module. However, whenever you want mocking your functions or methods, you need additional packages. Languages like Python provide standardised libraries and frameworks that make it easy to mock methods and functions inside an impure function or method. With python unit tests are pretty easy thus achieving a 100% test coverage is the norm. Go or Golang is a light weight language that is not C based.


Warning: This might inflate executable file size a little bit and cost a little runtime performance. IMO, this would be better if golang has such feature like macro or function decorator.

If you want to mock functions without changing its API, the easiest way is to change the implementation a little bit:

func getPage(url string) string {
  if GetPageMock != nil {
    return GetPageMock()
  }

  // getPage real implementation goes here!
}

func downloader() {
  if GetPageMock != nil {
    return GetPageMock()
  }

  // getPage real implementation goes here!
}

var GetPageMock func(url string) string = nil
var DownloaderMock func() = nil

This way we can actually mock one function out of the others. For more convenient we can provide such mocking boilerplate:

// download.go
func getPage(url string) string {
  if m.GetPageMock != nil {
    return m.GetPageMock()
  }

  // getPage real implementation goes here!
}

func downloader() {
  if m.GetPageMock != nil {
    return m.GetPageMock()
  }

  // getPage real implementation goes here!
}

type MockHandler struct {
  GetPage func(url string) string
  Downloader func()
}

var m *MockHandler = new(MockHandler)

func Mock(handler *MockHandler) {
  m = handler
}

In test file:

// download_test.go
func GetPageMock(url string) string {
  // ...
}

func TestDownloader(t *testing.T) {
  Mock(&MockHandler{
    GetPage: GetPageMock,
  })

  // Test implementation goes here!

  Mock(new(MockHandler)) // Reset mocked functions
}

How to Unit Test and Mock a Function in Go, As an example, if the Authenticate(user User) bool function executes a remote call to fulfill its purpose, it can be substituted by a custom mock  Mock Functions Mock functions are also known as "spies", because they let you spy on the behavior of a function that is called indirectly by some other code, rather than only testing the output. You can create a mock function with jest.fn (). If no implementation is given, the mock function will return undefined when invoked.


Mocking Golang with Interfaces In Real Life · Deploy Everyday, funcmock is a Function Mocking Framework in Go which replaces the lexical placeholder of the function with a mock. It is primarily intended to be used for testing  I made a design decision that our Countdown function would not be responsible for how long the sleep is. This simplifies our code a little for now at least and means a user of our function can configure that sleepiness however they like. Now we need to make a mock of it for our tests to use.


Smarp/funcmock: Mocking Golang functions, We'll start by defining a really simple Go program that features one exported function, Calculate() . main.go. package main import ( "fmt" )  Mocking Function A mock is a convincing duplicate of an object or module without any real inner workings. It might have a tiny bit of functionality, but compared to the real thing, it’s a mock. It can be created automatically by Jest or manually.


Improving Your Go Tests and Mocks With Testify, In this example, the Fetch() method is just sleeping for a pre-defined duration, but imagine that it is a real external API call, involving a slow and  So in conclusion, test the concrete type and only mock the interface of the consumer when you test the consumer method/function. Have a look at: SOLID Go Design level 2