Gomuti is DSL for mocking Golang interfaces, inspired by Gomega and drawing upon Gomega matchers to dispatch mock method calls. With a Ginkgo-like DSL for programming mock behavior, Gomuti makes it easy to write beautiful, well-isolated unit tests.
Mocks can also be spies and stubs, enabling behavior-driven development and terse, easy-to-maintain mock setup.
Imagine you have an interface that you want to mock.
type Adder interface { Add(l, r int64) int64 }To properly mock this interface, you need to create a struct type that has the same methods. The struct also holds two Gomuti-related fields that keep state about the programmed behavior of the mock and the observed method calls:
import gtypes "github.com/xeger/gomuti/types" type MockAdder struct { Mock gtypes.Mock Spy gtypes.Spy } func(m *MockAdder) Add(l, r int64) int64 { m.Spy.Observe(l, r) r := m.Mock.Call("Add", l, r) return r[0].(int64) }In reality you would use Mongoose to generate a mock type and methods for every interface in your package, but a hand-coded mock is fine for example purposes.
To program behavior into your mock, use the DSL methods in the gomuti package. Allow() instructs your mock to expect a method call and tells it what to return.
Imagine you're writing unit tests for the Multiplier type and you want to isolate yourself from bugs in Adder.
import ( . "github.com/onsi/ginkgo" . "github.com/xeger/gomuti" ) Describe("multiplier", func() { var subject *multiplier var adder Adder BeforeEach(func() { adder = &MockAdder{} m := &multiplier{Adder:a} }) It("computes the product of two integers", func() { Allow(adder).Call("Add").With(5,5).Return(10) Allow(adder).Call("Add").With(10,5).Return(15) result := subject.Multiply(3,5)) Expect(result).To(Equal(15)) }) })The Allow() DSL can use any Gomega matcher for method parameters and Gomuti provides a few matchers of its own; together, these allow you to mock sophisticated behavior. Imagine your adder has a new AddStuff() feature that adds arbitrarily-typed values.
Allow(adder).Call("AddStuff").With(AnythingOfType("bool"), Anything()).Return(true)You can use the HaveCall() Gomega matcher to spy on your mock, verifying the number of calls actually made to your mock as well as the specific parameter values.
integer := AnythingOfType("int64") Expect(adder).To(HaveCall("Add").With(integer, integer).Times(2))If you generate your mocks with Mongoose, then they come with a boolean Stub field; setting this field to true causes all methods to return zero values unless a matching call has been programmed.
Gomuti has some method aliases that imitate RSpec's plain-English DSL.
Expect(adder).ToReceive("Add").With(42,Anything()).AndReturn(42) adder.Add(42, 7) Expect(adder).To(HaveReceived("Add").Once())Gomuti's long-form DSL uses concise English words as method names. There is also a short-form DSL built around the method gomuti.Â(). To produce the  character, type Alt+0194 on Windows keyboards or Shift+Option+M on Mac keyboards (as a mnemonic, think " allows my Mock the option of being called.")
Short-form equivalents are provided for ToReceive() and other chained methods, and a super-terse form of  delivers maximum brevity. If we also use Gomega's Ω method, our tests get very terse indeed. (Some would say "unreadable," but beauty is in the eye of the beholder.)
// Super terse DSL Â(adder,"Add",5,5).Return(10) // Moderately terse DSL with complex matcher. big := BeNumerically(">",2**32-1) Â(adder).Call("Add").With(big,Anything()).Panic("integer overflow") Ω(subject.Multiply(2,5)).Should(Equal(10)) Ω(adder).Should(HaveCall("Add").Times(2)) Ω(func() { subject.Multiply(2**32-1,1) }).Should(Panic())Long and short method calls are interchangeable; even when using the long-form Allow(), we recommended using Call() instead of ToReceive() because the word "receive" is usually associated with the channel-receive operation.
Check the frequently-asked questions to see if your problem is common.
Make sure to check Gomuti's godocs for relevant information.
If you think Gomuti is missing a feature, check the roadmap to see if a similar feature is already planned.
If you still need help, open an Issue. Clearly explain your problem, steps to reproduce, and your ideal solution (if known).
Fork the xeger/gomuti repository on GitHub; make your changes; open a pull request.

