How to test whether a function was called

6,401 views
Skip to first unread message

Kosztka Imre Dávid

unread,
Oct 7, 2012, 2:09:21 AM10/7/12
to golang-nuts
Hi,

How can I test that a function from a package was called or not?
E.g. http.ListenAndServe(":12345", nil)

Regards,
Kocka
--
Name : Kosztka Imre Dávid
E-mail: kosz...@gmail.com
Phone number: +36309213462
Mailing address: H-3700, Hungary Kazincbarcika Szeder utca 2.

Jesse McNelis

unread,
Oct 7, 2012, 2:16:35 AM10/7/12
to Kosztka Imre Dávid, golang-nuts
On Sun, Oct 7, 2012 at 5:09 PM, Kosztka Imre Dávid <kosz...@gmail.com> wrote:
> How can I test that a function from a package was called or not?
> E.g. http.ListenAndServe(":12345", nil)

This question seems like it's an attempt to solve some other problem.
Telling us the real problem and the why will allow us to help you better.

What do you hope to gain from knowing that a function was called? Test coverage?

--
=====================
http://jessta.id.au

Kosztka Imre Dávid

unread,
Oct 7, 2012, 3:03:34 AM10/7/12
to Jesse McNelis, golang-nuts
You're right. Actually I would like to be able stub/mock/fake/whatever
a function call, to have more like a unit test and not an integration
test.

Regards,
Kocka

2012/10/7 Jesse McNelis <jes...@jessta.id.au>:

Jan Mercl

unread,
Oct 7, 2012, 3:21:14 AM10/7/12
to Kosztka Imre Dávid, Jesse McNelis, golang-nuts
On Sun, Oct 7, 2012 at 9:03 AM, Kosztka Imre Dávid <kosz...@gmail.com> wrote:
> You're right. Actually I would like to be able stub/mock/fake/whatever
> a function call, to have more like a unit test and not an integration
> test.

I believe that information can be extracted by
https://github.com/axw/gocov. ATM it doesn't instrument stdlib
packages but the mechanism is IMO mostly ready for that too.

-j

Rémy Oudompheng

unread,
Oct 7, 2012, 3:58:00 AM10/7/12
to Kosztka Imre Dávid, Jesse McNelis, golang-nuts
On 2012/10/7 Kosztka Imre Dávid <kosz...@gmail.com> wrote:
> You're right. Actually I would like to be able stub/mock/fake/whatever
> a function call, to have more like a unit test and not an integration
> test.

Make the function a variable or use an interface and replace it by
something you like.
What is the thing you are testing?

Rémy.

Kosztka Imre Dávid

unread,
Oct 7, 2012, 7:20:55 AM10/7/12
to Rémy Oudompheng, Jesse McNelis, golang-nuts
> Make the function a variable or use an interface and replace it by
> something you like.

Thank you! I was looking for this.

There was no special stuff to test, I was just interested in the
theoretical solution, but I think now I will start to play with it.

Trung Pham

unread,
Oct 24, 2012, 1:04:03 AM10/24/12
to golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
Mocking is not trivial in Go.

Say if you have an interface that has 100 functions. In your unit test, you must manually define 100 methods for the mocked object in order to fulfill the interface's requirement.

And it is impossible to mock constructors and static methods.

This is something that you have to be willing to give up when working with Go. :'(

I think most Go adopters don't come from a TTD background, and don't have an appreciation for a good mocking library...

As for me, I'm debating if I should overlook the lack of mocking support since I don't want to sacrifice the easy of testability(code quality) for performance gain.

If you want a static typed language with good concurrent support and TDD friendly. Checkout Scala, and see how easy it is to write unit test that mocks stuffs: http://www.scalatest.org/user_guide/testing_with_mock_objects

David Symonds

unread,
Oct 24, 2012, 1:07:36 AM10/24/12
to Trung Pham, golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
On Wed, Oct 24, 2012 at 4:04 PM, Trung Pham <tr...@phamcom.com> wrote:

> And it is impossible to mock constructors and static methods.

False (though I'm not sure what you mean by "static methods"; is that
a function?).

-----
package foo

type Whatever struct { ... }

var NewWhatever = func(...) *Whatever { ... }
----
package something_test

import "path/to/foo"

...

// replace NewWhatever
foo.NewWhatever = func(...) *Whatever { ... }
----

The same approach applies to any top-level functions.

Trung Pham

unread,
Oct 24, 2012, 1:21:35 AM10/24/12
to golan...@googlegroups.com, Trung Pham, Rémy Oudompheng, Jesse McNelis
What you suggested is only possible if the function is assigned to a variable.

If the foo package looks like this then you're screwed. And most of the time you have no control over how third party package is written.
---
package foo
type Whatever struct { ... } 

func NewWhatever(...) *Whatever { ... } 

David Symonds

unread,
Oct 24, 2012, 1:23:14 AM10/24/12
to Trung Pham, golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
On Wed, Oct 24, 2012 at 4:21 PM, Trung Pham <tr...@phamcom.com> wrote:

> What you suggested is only possible if the function is assigned to a
> variable.
>
> If the foo package looks like this then you're screwed. And most of the time
> you have no control over how third party package is written.

If you don't have control over that third_party package, and want to
mock/fake something from it, don't use it directly. Write your own var
var fooNewWhatever = foo.NewWhatever
and use that in your code, and then you can change it for your test.

Trung Pham

unread,
Oct 24, 2012, 1:31:24 AM10/24/12
to golan...@googlegroups.com, Trung Pham, Rémy Oudompheng, Jesse McNelis
David, thank you for your suggestions. What you mentioned seem like good workarounds in Go.

Though, you should checkout http://www.scalatest.org/user_guide/testing_with_mock_objects anyway and see if it is indeed greener on the other side. :)

Henrik Johansson

unread,
Oct 24, 2012, 1:40:12 AM10/24/12
to Trung Pham, golang-nuts, Jesse McNelis, Rémy Oudompheng

But the mocking frameworks you link too are impressive feats of coding to work around quirks in Java. They only make it look easy because someone else did the heavy lifting for you.

--
 
 

Sanjay

unread,
Oct 24, 2012, 1:51:28 AM10/24/12
to golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
You can create 1 struct that has stubs of all the methods you need, and embed it in all your mocks, so your mocks only need to implement the few methods they actually need to override for testing. Also, if you update the interface with a new method, you just need to update 1 struct rather than all your mock objects.

I suppose a tool could be created that would write this stub implementation for you, but I tend to keep interfaces brief, so its never been a problem for me. A 100 method interface sounds daunting...

Nigel Tao

unread,
Oct 24, 2012, 2:25:49 AM10/24/12
to Trung Pham, golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
On 24 October 2012 16:04, Trung Pham <tr...@phamcom.com> wrote:
> Say if you have an interface that has 100 functions.

Most Go interfaces that I've seen have only a few methods, often just
one. The biggest had probably had 10 or 20 at most, and was unusual.
Having 100 suggests to me that there's a better way to factor the
code.

Larry Clapp

unread,
Oct 24, 2012, 10:33:27 AM10/24/12
to golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis
It seems to me that if your "Test Driven Development" is truly Driven by Tests, then, given that Go is so young and doesn't have a mocking library, you'd Develop your code in such a way that you don't need a large mocking library.

And if you don't, well, whose fault is that?

-- L

Joubin Houshyar

unread,
Oct 24, 2012, 11:22:05 AM10/24/12
to golan...@googlegroups.com, Rémy Oudompheng, Jesse McNelis


On Wednesday, October 24, 2012 1:04:03 AM UTC-4, Trung Pham wrote:
Mocking is not trivial in Go.

Say if you have an interface that has 100 functions. In your unit test, you must manually define 100 methods for the mocked object in order to fulfill the interface's requirement.

I feel your pain:


This is WIP and I'm typically stretched in n directions so I haven't touched in a while but its on the todo list.

Spec driven (pseudo contracts (to address lack of metadata constructs in Go)) 

to drive a test generator:

with associated test templates:

(Btw, that above is already pulling its weight and has fished out a few bugs in the driver.  Also on the todo list .. )))

The code gaps notwithstanding, the path to ~automated BB/WB testing is quite clear.  


And it is impossible to mock constructors and static methods. 

This is something that you have to be willing to give up when working with Go. :'(

I think most Go adopters don't come from a TTD background, and don't have an appreciation for a good mocking library...

As for me, I'm debating if I should overlook the lack of mocking support since I don't want to sacrifice the easy of testability(code quality) for performance gain.

If you want a static typed language with good concurrent support and TDD friendly. Checkout Scala, and see how easy it is to write unit test that mocks stuffs: http://www.scalatest.org/user_guide/testing_with_mock_objects

Ok, so the disconnect here is that JVM's runtime metadata infrastructure is far richer than Go's (reflection). Also, as mentioned already in this thread, a fairly significant amount of geek hours have been invested in the above stack.  So (the hypothetical) you need(s) to roll up your sleeves and address this; and it appears that both culturally (gophers) and technically (the platform) favor /tool pipelines/ over runtime platform services.  I anticipate that is what will materialize at some point by the community in the (~near) future.

Kamil Kisiel

unread,
Oct 24, 2012, 12:45:40 PM10/24/12
to golan...@googlegroups.com
Is it actually necessary to have one big Client interface for Redis? You may be able to split it up in to interfaces that have subsets of the complete functionality. That could simplify the creation of implementations that only need to handle a few operations.
Message has been deleted

bryanturley

unread,
Oct 24, 2012, 3:20:00 PM10/24/12
to golan...@googlegroups.com
Yes interfaces should be simple not complex.
Sounds like you are trying to do OO paradigm in go, and not the new awesome interface paradigm.

Simpler definitions should ease testing as well.

Joubin Houshyar

unread,
Oct 24, 2012, 6:40:49 PM10/24/12
to golan...@googlegroups.com


On Wednesday, October 24, 2012 12:45:41 PM UTC-4, Kamil Kisiel wrote:
Is it actually necessary to have one big Client interface for Redis? You may be able to split it up in to interfaces that have subsets of the complete functionality. That could simplify the creation of implementations that only need to handle a few operations.

Go-Redis is fully modular.  You are free to define an API that suites your requirements.  

Reply all
Reply to author
Forward
0 new messages