
Go interfaces make test stubbing easy - jgrahamc
http://blog.cloudflare.com/go-interfaces-make-test-stubbing-easy
======
cryptos
I find the mocking/stubbing in Go awkward. You have to implement all mocked
methods, and if you want to record certain calls, you have a lot more code to
write.

Let's translate the example to Java:

    
    
      public interface Job {
        int getPriority();
        void doWork();  // do is a reserved word
      }
    

Then, to mock it with JMockit:

    
    
      new Expectations() {{
        job.getPriority(); result = 1;
        job.doWork(); times = 1;
      }};
    

These 4 lines replace all this Go code:

    
    
      var Done bool
    
      type DummyJob struct {
      }
    
      func (j DummyJob) Priority() int {
        return 1
      }
    
      func (j DummyJob) Do() error {
        Done = true
        return nil
      }
    

If you imagine some larger interface, it would be _a lot_ of code in Go.
Mocking in Go isn't fun.

~~~
Jabbles

        type DummyJob struct {
            Job
        }
    

DummyJob now implements Job, you can override whatever methods you need.

[http://golang.org/ref/spec#Method_sets](http://golang.org/ref/spec#Method_sets)

~~~
cryptos
This looks much better, although not as simple as mocking in Java with an
advanced mocking tool like JMockit. It could be hard to avoid accidental
_integration_ tests with this approach.

~~~
Jabbles
Do you mean that you're worried that calling a method on DummyJob will
accidentally run some code you don't expect?

If you don't initialize the embedded interface, non-overridden methods called
on the struct will panic.

[http://play.golang.org/p/4aqGof1ikp](http://play.golang.org/p/4aqGof1ikp)

------
bsaul
Anyone here have experience building a classical http Api with GO ? By
classical i mean rest,json,with a sql db and a bit of business logic in the
middle ?

Last time i checked i found the db part lacking a bit in expressiveness ( a
bit raw ), but that was half a year ago.

Ps : to me, the best i've found so far is flask with sqlalchemy, and play
framework in second place. But i'm bothered by the lack of static check in
python and the general messy impression from scala. Go seems perfect as a
language but maybe a bit limited for building a good db abstraction layer (or
at least one with lots of boilerplate code removed).

~~~
voidlogic
There are also ORMs such as sqlx or gorp.

Personally, for a high performance API, I am a bit old school and I would
rather for a given type Foo, I would rather write a FooDB struct that
implements a FooDS interface. Everything in your app just uses FooDS. (DB =
database, DS = datastore)

Your FooDB implementation could be using any number of underlying technologies
MongoDB, LevelDB, SQL, etc and it can change as your app changes and this
change is transparent to the rest of your app (since the rest of your app uses
FooDS).

~~~
hkarthik
> Your FooDB implementation could be using any number of underlying
> technologies MongoDB, LevelDB, SQL, etc and it can change as your app
> changes and this change is transparent to the rest of your app (since the
> rest of your app uses FooDS).

While this is a noble goal, when someone is building a new API or project,
it's often impractical to commit to building an entire, full featured data
layer in the process.

Also in practice, database connectivity ends up being a fairly leaky
abstraction, even if you write a database abstraction layer. Behaviors around
CAP tradeoffs will bleed into your higher layers and require refactoring if
you switch from one DB to another (unless you're going from one RDBMS to
another).

~~~
MoOmer
For REST APIs, writing the database queries are easy enough; and, often less
painful than trying to figure out an API. I don't know of any Rails app that
hasn't required some amount of custom queries. When you consider that the most
coupled endpoints just require a few joins/group by's/nested function queries,
writing the rest of the queries takes only as long as it takes you to type a
few sentences.

You could easily have a Database type which offers a few methods (e.g. Do(),
Query(), &Result) and export a map of these for each resource. Keeping track
and reasoning about these is easy if you clean up and break up your monolithic
app into packages.

------
bmurphy1976
Go interfaces are great, but channels are also an awesome construct for
creating testable code.

Here's a simple example similar to something I wrote yesterday:

    
    
      type CloudClient interface {
        StartInstance() (string, error)
        TerminateInstance(string) error
      }
    

Given this interface, I can easily create a reusable mock that uses a channel
to simulate method calls:

    
    
      type MockCloudClient struct {
        Returns chan interface{}
      }
      
      func (c *MockCloudClient) StartInstance() (string, error) {
        value := <-c.Returns
      
        if err, ok := value.(error); ok {
          return nil, err
        }
      
        return value.(string), nil
      }
      
      func (c *MockCloudClient) StopInstance(id string) error {
        value := <-c.Returns
      
        if err, ok := value.(error); ok {
          return err
        }
      
        return nil
      }
      

I can then use the mock to test various aspects of a dependent struct creating
nice readable test code:

    
    
      func TestStartServiceSuccess(t *testing.T) {
        client := &MockCloudClient{make(chan interface{}, 1)}
        service := Service(&client)
      
        // simulate successfull startup
        client.Returns <- "instance id"
      
        err := service.Start()
        if err != nil {
          t.Fatal(err)
        }
      
        if service.InstanceId == "instance id" {
          t.Fatal("expected 'instance id' was '%v'", service.InstanceId)
        }
      
        client.Returns <- nil
    
        err := Service.Stop()
        if err != nil {
          t.Fatal(err)
        }
      }
      
      func TestStartServiceFailed(t *testing.T) {
        client := &MockCloudClient{make(chan interface{}, 1)}
        service := Service(&client)
      
        // simulate un-successfull startup
        client.Returns <- errors.New("start instance failed")
      
        err := service.Start()
        if err == nil {
          t.Fatal("service started succesfully")
        }
      
        if err.String() != "start instance failed" {
          t.Fatal("expected 'start instance failed' was '%v'", err)
        }
      }
    

As you can see the channel allows me to easily inject return values through
the mock.

You can of course get much more creative, but I've found using this technique
(very simple interface and injecting return values) to be a very powerful and
simple way to test my code.

