mocking/stubbing method in unit test

11,674 views
Skip to first unread message

tr...@phamcom.com

unread,
May 28, 2012, 3:43:17 PM5/28/12
to golan...@googlegroups.com
How do I mock/stub a method in my unit test in order to remove dependency?

This is relative simple to do in a dynamic language like ruby or javascript. Since it lets you redefine any method on the fly, and restore it afterward.

Mocking is an extremely useful feature when it comes to unit testing. Say if your code makes an externally http request to get something. In your unit test, you would not want to actually make the http call because it's expensive, unreliable, and you have no way of controlling what you will get. Rather you would mock the http response to be some fixed result, and test that given outcome.

For example, in ruby I can do something like this.

HTTP.should_receive(:get).and_return("Hello world")

HTTP.get("http://example.com").should == "Hello world"

Please let me know what library or tool you use for mocking method in Go.

Thank you.

roger peppe

unread,
May 29, 2012, 4:51:27 AM5/29/12
to tr...@phamcom.com, golan...@googlegroups.com
For testing code that makes network calls like http, I often set up
a local server and make the code use the local address rather
than the usual server address. The local server is within the
same code and so you can talk to it to determine
what has happened, or to set its expectations.

A good example of this kind of approach is to be found in
Gustavo Niemeyer's goamz library (go get launchpad.net/goamz/ec2).
For instance, take a look at
http://bazaar.launchpad.net/+branch/goamz/view/head:/ec2/ec2_test.go
and check out the testServer.PrepareResponse and WaitRequest calls.

You can also test an http handler directly by mocking up an http.Request and
calling the ServeHTTP method.

John Beisley

unread,
May 29, 2012, 5:25:54 AM5/29/12
to tr...@phamcom.com, golan...@googlegroups.com
I use https://github.com/dsymonds/gomock which will generate a mock
that implements an interface that you specify, and allows you to
record expected calls against it.

On 28 May 2012 20:43, <tr...@phamcom.com> wrote:

Trung Pham

unread,
May 29, 2012, 7:29:32 PM5/29/12
to golan...@googlegroups.com, tr...@phamcom.com
This is probably not a good idea. Soon you will need a test server for mySQL, memcache, search, etc.... And it doesn't address complicated method within your application that has been tested by its own unit test, but you want to hide it in the current unit test and use a mocked return value instead.

Trung Pham

unread,
May 29, 2012, 7:37:22 PM5/29/12
to golan...@googlegroups.com, tr...@phamcom.com
It seems like there is a big over head when it comes to mocking something in Go.

Unless Go allows developers to redefine methods on the fly, the language does not look very friendly to Test Driven Developers, comparing to other dynamic languages like Ruby or Javascript.

I'm not bashing Go or anything, just want to understand its limitations. :)

Jen Carlile

unread,
May 29, 2012, 8:42:37 PM5/29/12
to golan...@googlegroups.com, tr...@phamcom.com
+1 for gomock.  The built-in net/http/httptest package is also useful in testing, though not directing related to mocks or stubs


On Tuesday, May 29, 2012 2:25:54 AM UTC-7, John Beisley wrote:
I use https://github.com/dsymonds/gomock which will generate a mock
that implements an interface that you specify, and allows you to
record expected calls against it.

Kyle Lemons

unread,
May 29, 2012, 8:49:30 PM5/29/12
to Trung Pham, golan...@googlegroups.com
On Tue, May 29, 2012 at 4:37 PM, Trung Pham <tr...@phamcom.com> wrote:
It seems like there is a big over head when it comes to mocking something in Go.

Unless Go allows developers to redefine methods on the fly, the language does not look very friendly to Test Driven Developers, comparing to other dynamic languages like Ruby or Javascript.

For the record, TDD works superbly in Go.  You don't design your code to be tested by Ruby, you design it to be tested by Go, and thus you have interfaces in all the right places to begin with, and they're nice and narrow and easy to stub out.  It's when you try to inject dependencies after the fact that you can run into problems.

Trung Pham

unread,
May 29, 2012, 9:47:18 PM5/29/12
to golan...@googlegroups.com, Trung Pham
I don't mean for this to be a language battle.

But as for someone coming from a dynamic language where you can stub a method using a single line of code. It makes unit testing a pleasure experience, in turn, encourages test driven behavior.
And if I have to jump through hoops to mock something in Go in order to remove dependencies, then it makes unit testing a little harder to swallow.

Testing is an important part of software development that must be carefully evaluated before diving into a new language.

I'm just trying to do my homework. :)

Brad Fitzpatrick

unread,
May 29, 2012, 10:08:20 PM5/29/12
to Trung Pham, golan...@googlegroups.com
IMHO, Go is very near Python in terms of testability.  It's much closer to Python than Java or C++, for sure.  You can very often make your test interfaces purely in the *_test.go files and leave the real files alone.  (at least once you've gotten the hang of how to write testable Go code, but it doesn't take much time to learn)

In fact, considering how much of my Python testing is unit tests for checking the behavior of type errors, Go's probably less work overall since the language & compiler make those tests unnecessary.

Trung Pham

unread,
May 29, 2012, 10:50:46 PM5/29/12
to golan...@googlegroups.com, Trung Pham
Do you guys know of any tutorial or example that talks about unit testing in Go and especially dealing with removing dependencies?

Curse who named Go, Go. It makes it impossible to search for anything related to Go...

Thanks.

Daniel Brain

unread,
May 29, 2012, 11:02:31 PM5/29/12
to Trung Pham, golan...@googlegroups.com
Try searching with golang instead of just go, i.e. "golang testing".

Thomas Nadin

unread,
May 30, 2012, 4:43:33 AM5/30/12
to golan...@googlegroups.com, Trung Pham
Still young to Go myself however I recently watched Let's Go Further, a presentation by Sameer Ajmani. In it he uses an example of Google Search, and querying multiple backends by stubbing them out. I've linked you to the point in the presentation where that begins but I wold definitely recommend watching the whole thing, it has shed light on a lot of Go concepts for me.

As for searching for anything Go related, use 'Golang' as Daniel Brain suggested, works for me.

Kyle Lemons

unread,
May 30, 2012, 11:49:47 AM5/30/12
to Trung Pham, golan...@googlegroups.com
It's not a tutorial, but there is a wiki article http://code.google.com/p/go-wiki/wiki/TableDrivenTests that is one example of a test that, in my mind, shows the huge cultural difference between Go tests and Python tests.  In python, each of those cases would often be a copy/pasted function.

On Tue, May 29, 2012 at 7:50 PM, Trung Pham <tr...@phamcom.com> wrote:
Do you guys know of any tutorial or example that talks about unit testing in Go and especially dealing with removing dependencies?

Curse who named Go, Go. It makes it impossible to search for anything related to Go...

Use "golang" when searching on Google.

Trung Pham

unread,
May 30, 2012, 7:27:57 PM5/30/12
to golan...@googlegroups.com, Trung Pham
None of the examples linked here showed how to remove dependencies within unit tests.

Maybe someone who is more experienced with Go can create a tutorial focusing on non-trivial unit tests in Go. That would be very helpful for the people coming from TDD background. :)

Thanks.

Kyle Lemons

unread,
May 31, 2012, 11:40:20 AM5/31/12
to Trung Pham, golan...@googlegroups.com
On Wed, May 30, 2012 at 4:27 PM, Trung Pham <tr...@phamcom.com> wrote:
None of the examples linked here showed how to remove dependencies within unit tests.

Maybe someone who is more experienced with Go can create a tutorial focusing on non-trivial unit tests in Go. That would be very helpful for the people coming from TDD background. :)

To be clear, TDD is a philosophy and is completely orthogonal to the tools with which you construct your unit test.  Dependency injection -- which must be done explicitly in Go -- is merely one possible tool in your belt when writing unit tests.  You will find some of it in the standard library (see the net.Conn mock/fake in http://golang.org/src/pkg/net/smtp/smtp_test.go), but most of it is simply a table-driven test controlling the inputs and checking the outputs of a function or method, because that's much simpler.  Even more common than that net.Conn-style mock/fake are passing bytes.Buffer as an io.Reader or io.Writer to simulate input coming from somewhere or going somewhere.  Interfaces make this very natural and part of a good design, and it's all completely independent of TDD.

Trung Pham

unread,
Jun 23, 2012, 8:32:37 PM6/23/12
to golan...@googlegroups.com, Trung Pham
Mocking seems to be pretty easy in Objective-C(also compiled) using this library, http://ocmock.org/.

Can such library be ported to Go?

Thanks.

Trung Pham

unread,
Jul 5, 2012, 3:41:16 PM7/5/12
to golan...@googlegroups.com, Trung Pham
I figured out how to do what I want in Go. Basically, turn everything into a var, and redefine it in my unit test, then restore it afterward.

In myapp.go file

package myapp

var MyFunction = func () int{
//do something very complicated.
}

instead of
func MyFunction() int{
//do something very complicated
}


And in my unit test

import "myapp"

func TestSomething(t testing.T){

oldMyFunction = myapp.MyFunction
myapp.MyFunction = func() int{
  //simply return 1; 
}

//call something that call myapp.MyFunction


//restore myapp.MyFunction after my test is done

myapp.MyFunction = oldMyFunction

}

 

It's ugly but it serves my purpose. However, I can do this on packages that I wrote because other packages do not define their function as variables.



On Saturday, June 23, 2012 7:32:52 PM UTC-7, sdeg...@8thlight.com wrote:
No, it's not possible because OCMock makes use of ObjC's metaprogramming abilities to create methods on an object at run-time. There may be some other technique to simplify the redundancy in implementation which we'll keep seeing, and the community seems to be working on this over time. But for now the solution is to write your own mocks and make careful use of interfaces. This is the only downside to having no meta-programming, but it's totally worth it, because in every other situation, magic sucks.

-Steven

John Beisley

unread,
Aug 22, 2012, 9:04:15 AM8/22/12
to rock...@google.com, golan...@googlegroups.com, Trung Pham
You could always do something like: http://play.golang.org/p/y3RqWYVtpt

It solves the problem without a global, but does mean splitting your
function into a public function (that simply
wraps the call with normal implementation), and a private function
that uses the implementation it is given.

On 21 August 2012 17:39, <rock...@google.com> wrote:
> But then anyone in the world using your package could re-define MyFunction
> to be whatever they want. This could be a major problem for encapsulation
> and for the integrity of your package. Alternatively, you could have
> MyFunction delegate to myFunction and make myFunction a var. Then you can
> still use your scheme for testing, and still prevent the rest of the world
> from changing your MyFunction. But personally, I never liked redefining
> functions and then switching them back because what happens if your test
> harness is multi-threaded?

Isaac Mosquera

unread,
Sep 19, 2013, 3:32:59 PM9/19/13
to golan...@googlegroups.com, rock...@google.com, Trung Pham
I know I'm bringing up an old topic, but is there anything wrong with Trung Pham's approach to defining these functions as vars and redefining them at test time?

roger peppe

unread,
Sep 19, 2013, 3:48:35 PM9/19/13
to Isaac Mosquera, golang-nuts, rock...@google.com, Trung Pham
On 19 September 2013 20:32, Isaac Mosquera <is...@sharethis.com> wrote:
> I know I'm bringing up an old topic, but is there anything wrong with Trung
> Pham's approach to defining these functions as vars and redefining them at
> test time?

We use that approach sometimes.

The convention goes something like this:

in the code:

package mypkg

// The following are variables so that they can be
// changed by tests.
var (
someMethod = (*somepkg.SomeType).Method
someFunc = somepkg.SomeFunc
)

func myFunc() {
someMethod(obj, args)
someFunc(args)
}

in export_test.go:

package mypkg
var (
SomeMethod = &someMethod
SomeFunc = &someFunc
)

in some_test.go:

package mypg_test

func TestSomething(t *testing.T) {
defer testinghelpers.Patch(mypkg.SomeMethod, func(*somepkg.SomeType, args) {
mock method
}).Restore()
defer testinghelpers.Patch(mypkg.SomeFunc, func(args) {
mock function
}).Restore()
actual test
}

where testinghelpers.Patch is defined like this:
http://play.golang.org/p/oLF1XnRX3C
and testinghelpers has a shorter package name :-)

It's good to avoid this approach where possible, but sometimes
it's difficult to get good test coverage without it, particular for
testing error paths.

Julian Phillips

unread,
Sep 19, 2013, 5:44:10 PM9/19/13
to roger peppe, Isaac Mosquera, golang-nuts, rock...@google.com, Trung Pham
I recently wrote a tool (github.com/qur/withmock) that will mock out
packages automatically for getting into those icky corners when testing
...

So you might have code:

package mypkg

import "somepkg"

func MyFunc() {
somepkg.SomeFunction()
}

with test code:

package mypkg_test

import (
"somepkg" // mock
"code.google.com/p/gomock"
)

func TestMyFunc(t *testing.T) {
ctrl := gomock.NewController()
defer crtl.Finish()
somepkg.MOCK().SetController(ctrl)
somepkg.EXPECT().SomeFunction()
MyFunc()
}

--
Julian

Isaac Mosquera

unread,
Sep 19, 2013, 5:51:19 PM9/19/13
to golan...@googlegroups.com, roger peppe, Isaac Mosquera, rock...@google.com, Trung Pham
Julian/rog - thanks for the libraries & code.  This is exactly what i'm looking for.  Thanks!

Michael Whatcott

unread,
Sep 20, 2013, 12:14:25 AM9/20/13
to golan...@googlegroups.com

Nathan Youngman

unread,
Sep 20, 2013, 2:59:24 AM9/20/13
to golan...@googlegroups.com
There's this article on httptest:
https://willnorris.com/

Here's an article on using the lambda approach:
http://openmymind.net/Dependency-Injection-In-Go/

Though so far I'm just using interfaces for doubles/fakes. I haven't gotten into mocking/expectations in Go yet.

Reply all
Reply to author
Forward
0 new messages