In this talk, I’m introducing Pegomock, a mocking framework for Go, that I have written over the last 2 years. By quickly going through the idea of Dependency Injection, I'm explaining why mocks are useful in general. Afterwards, I'm diving a bit deeper into how to use Pegomock and why I think it is better than its alternatives.
9. Unit Testing the CheckoutService
9
fakeShippingService := ...
fakeCreditCardService := ...
fakeOrderService := ...
checkoutService := NewCheckoutService(
fakeShippingService,
fakeCreditCardService,
fakeOrderService)
When(fakeShippingService.GetShippingCost()).ThenReturn(5.90)
shoppingCart := ShoppingCart{[]Items{
Item{
Name: "Creation: Life and How to Make it - Steve Grand",
Price: 23.49,
},
}}
checkoutService.CheckOut(shoppingCart)
fakeCreditCardService.VerifyWasCalledOnce().Charge(15.90)
fakeOrderService.VerifyWasCalledOnce().Submit(shoppingCart)
10. Unit Testing the CheckoutService
10
fakeShippingService := NewMockShippingService()
fakeCreditCardService := NewMockCreditCardService()
fakeOrderService := NewMockOrderService()
checkoutService := NewCheckoutService(
fakeShippingService,
fakeCreditCardService,
fakeOrderService)
When(fakeShippingService.GetShippingCost()).ThenReturn(5.90)
shoppingCart := ShoppingCart{[]Items{
Item{
Name: "Creation: Life and How to Make it - Steve Grand",
Price: 23.49,
},
}}
checkoutService.CheckOut(shoppingCart)
fakeCreditCardService.VerifyWasCalledOnce().Charge(15.90)
fakeOrderService.VerifyWasCalledOnce().Submit(shoppingCart)
Generated by Pegomock
11. Pegomock CLI
11
# Install it:
go get github.com/petergtz/pegomock
go get github.com/petergtz/pegomock/pegomock
# Generate mocks:
pegomock generate ShippingService
pegomock generate CreditCardService
pegomock generate OrderService
17. Stubbing with Callbacks
17
phoneBook := NewMockPhoneBook()
// Stubbing:
When(phoneBook.GetPhoneNumber(AnyString())).Then(func(params []Param) ReturnValues {
return []ReturnValue{fmt.Sprintf("1-800-CALL-%v", strings.ToUpper(params[0]))}
}
// Prints "1-800-CALL-DAN":
fmt.Println(phoneBook.GetPhoneNumber("Dan"))
// Prints "1-800-CALL-TOM”:
fmt.Println(phoneBook.GetPhoneNumber("Tom"))
18. Verifying with Argument Capture
18
display := NewMockDisplay()
// Calling mock
display.Show("Hello")
display.Show("Hello, again")
display.Show("And again")
// Verification and getting captured arguments
text := display.VerifyWasCalled(AtLeast(1)).Show(AnyString()).getCapturedArguments()
// Captured arguments are from last invocation
Expect(text).To(Equal("And again"))
19. Verifying with Argument Capture
19
display := NewMockDisplay()
// Calling mock
display.Show("Hello")
display.Show("Hello, again")
display.Show("And again")
// Verification and getting all captured arguments
texts := display.VerifyWasCalled(AtLeast(1)).Show(AnyString()).getAllCapturedArguments()
// Captured arguments are a slice
Expect(texts).To(ConsistOf("Hello", "Hello, again", "And again"))
20. Why Pegomock, why not X?
• https://github.com/golang/mock
• https://github.com/maxbrunsfeld/counterfeiter
• Any others
20
Where X is:
21. GoMock
21
GoMock:
Use the mock in a test:
func TestMyThing(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mockObj := something.NewMockMyInterface(mockCtrl)
mockObj.EXPECT().SomeMethod(4, "blah")
// pass mockObj to a real object and play with it.
}
Pegomock:
func TestUsingMocks(t *testing.T) {
pegomock.RegisterMockTestingT(t)
mockObj := NewMyInterfaceMock()
// pass mockObj to a real object and play with it.
}