Logo

dev-resources.site

for different kinds of informations.

Ensure auto-generated code is always up-to-date with compile-time assertions in Go

Published at
7/30/2020
Categories
go
codegeneration
interface
Author
arashout
Categories
3 categories in total
go
open
codegeneration
open
interface
open
Author
8 person written this
arashout
open
Ensure auto-generated code is always up-to-date with compile-time assertions in Go

Introduction

Do you get annoyed when others (or you) forget to run the code generation command and now nothing works/code is out-dated?

Compile Time Assertions to the rescue!

Scenario

Suppose you have an interface:

type MyInterface interface {
    WithMethod(method string) MyInterface
}

This interface has an associated implementation:

type MyInterfaceImpl struct {
    privateField string
}
func (my *MyInterfaceImpl) MyInterface {
    // ... implementation code
}

Which you've have been auto-generating mock objects for using the awesome mockery package.

Why Though

You are doing this because you want users of your library to be able to mock your library.

  • Thus allowing them to isolate their own code when writing unit tests.
  • Meaning we don't actually use this mock in OUR tests, it is used by OTHERS

So the interface definition above is augmented with:

// Generate mocks by running "go generate ./..."
// go:generate mockery --name MyInteface
type MyInterface interface {
    WithMethod(method string) MyInterface
}

Which produces when go generate ./... is ran:
mocks/MyInterface.go

// MyInterface is an autogenerated mock type for the MyInterface type
type MyInterface struct {
    mock.Mock
}

// WithMethod provides a mock function with given fields: method
func (_m *MyInterface) WithMethod(method string) (pkg.MyInterface) {
// ... some mock implementation code

Problem

Now what happens when Greg who isn't aware of the auto-generated code, adds another method to MyInterface and MyInterfaceImpl:

type MyInterface interface {
    WithMethod(method string) MyInterface
    WithAnotherMethod(method string) MyInterface // New
}

Since the MyInterface has changed but Greg didn't auto-generate the mocks using go generate ./..., the mock object will not fulfill the interface and cannot be used for testing by downstream users (Thanks Greg)!

Solution

Add a compile-assertion above the interface definition after you have initially generated the mock object (Also add --inpackage flag to go generate command to avoid import cycles).

// Generate mocks by running "go generate ./..."
// go:generate mockery --name MyInteface --inpackage
var _ MyInterface = &MockMyInterface{} // COMPILE-TIME Assertion
type MyInterface interface {
    WithMethod(method string) MyInterface
}

Now if Greg adds another method but forgets to run go generate

var _ MyInterface = &MockMyInterface{}
type MyInterface interface {
    WithMethod(method string) MyInterface
    WithAnotherMethod(method string) MyInterface // New
}

He will get hit with:

cannot use &MockMyInterface literal (type *MockMyInterface) as type MyInterface in assignment:
    *MockMyInterface does not implement MyInterface (missing WithAnotherMethod method)

At which point, he might realize that he needs to add the method to the mock object using go generate.

Caveat: You will need to comment out the compile-time assertion var _ MyInterface = &MockMyInterface{} when running go generate/mockery tool

codegeneration Article's
30 articles in total
Favicon
Anvil: An attempt of saving time
Favicon
Spending Less Time on Boilerplate with Blackbird
Favicon
Boost Your Coding: Easy AI Code Generation Tricks
Favicon
How to Use AI Code Generation to Enhance Developer Productivity
Favicon
Understanding Abstract Syntax Trees
Favicon
Component Generation with Figma API: Bridging the Gap Between Development and Design
Favicon
How to Perform Code Generation with LLM Models
Favicon
Get rid of Copy/Paste with Plop Js!
Favicon
ABP Suite: Best CRUD Page Generation Tool for .NET
Favicon
Generating TypeScript Code for a Dynamic Country Flag React Component
Favicon
Top Free Code Generation tools, APIs, and Open Source models
Favicon
Introduction to Code Generation in Rust
Favicon
Best Code Generation APIs in 2023
Favicon
Crafting Prompt Templates for Code Generation
Favicon
NEW: Code Generation APIs available on Eden AI
Favicon
Declarative code generation in Unity
Favicon
Build a WebAssembly Language for Fun and Profit: Code Generation
Favicon
Using EDMX file and T4 in .NET Core to Generate Code (Entities, DTO, API, Services etc.)
Favicon
Freezed Kullanarak Flutter'da JSON Nasıl Ayrıştırılır? 💫 🌌 ✨
Favicon
Dotnet code generation overview by example
Favicon
Sparky's Tool Tips: NimbleText
Favicon
Coding the code versus coding the code that codes
Favicon
Build an entire React application in one command
Favicon
Ensure auto-generated code is always up-to-date with compile-time assertions in Go
Favicon
Sitecore Code Generation with Unicorn in 2020
Favicon
gosli: a little attempt to bring a bit of LINQ to Golang
Favicon
How to make a code generator in 5 minutes (or less)
Favicon
Adding Contexts via Go AST (Code Instrumentation)
Favicon
How to Add Generated HttpClient to ASP.NET Core Dependency Injection (Right Way)
Favicon
Using code generation to survive without generics in Go

Featured ones: