Git Product home page Git Product logo

gomockhandler's Introduction

gomockhandler

Mr. gomockhandler is the clever and fast manager of mocks generated by uber-go/mock (or golang/mock).

gomockhandler uses one config file to generate all mocks.

With gomockhandler,

  • You can generate mocks in parallel ๐Ÿš€.
  • You can check if mock is up-to-date โœจ.
  • You can manage your mocks in one config file ๐Ÿ“š.

Background

Some of you may often manage your mocks with go generate like below.

//go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG

But, it will take long time to generate a log of mocks with go generate ./..., because go generate executes mockgen one by one.

And we cannot easily check if mock is up-to-date; people often forget to update mocks when the interface is changed.

gomockhandler is created to solve all of these problems.

And with this background, it is designed to make it easy to switch from managing mocks with go generate to managing mocks with gomockhandler.

Install

You have to install mockgen first.

go install go.uber.org/mock/mockgen@latest

Next, install gomockhandler.

go install github.com/sanposhiho/gomockhandler@latest

How to use

gomockhandler is designed to be simple and does only three things.

  • generate/edit a config with CLI
  • generate mocks from config
  • check if mocks are up-to-date

These are the options for using the gomockhandler.

-config string
  The path to config file.
  The default value is "./gomockhandler.json"
  
-target_dir string
  Only mocks under the specified directory will be targeted for commands `check` and `mockgen`.
  By default, all files will be targeted.
  
-f bool
  If true, it will also generate mocks whose source has not been updated.
  The default value is false.

Getting started

You need a config for gomockhandler.

However, you don't need to generate/edit the config directly, it can be generated/edited from CLI.

configuring a new mock

You can configure a new mock to be generated with gomockhandler CLI.

If a gomockhandler config file does not exist, it will be created.

gomockhandler CLI is compatible with mockgen command which you can do anything you do with mockgen See golang/mock#running-mockgen for more information about the two modes and mockgen options.

Source mode:

gomockhandler -config=/path/to/gomockhandler.json -source=foo.go -destination=./mock/ [other mockgen options]

Reflect mode:

gomockhandler -config=/path/to/gomockhandler.json -destination=./mock/ [other mockgen options] database/sql/driver Conn,Driver

For example, suppose you want to configure the mock generated by the following mockgen command to be generated by gomockhandler

mockgen -source=foo.go -destination=../mock/

The following command will add the information of the mock you want to generate to the configuration. As you can see, you just need to think about the option config. (The default value is ./gomockhandler.json)

gomockhandler -config=/path/to/gomockhandler.json -source=foo.go -destination=../mock/

[TIPS] switch from go generate to gomockhandler

gomockhandler is designed to make it easy to switch from managing mocks with go generate to managing mocks with gomockhandler.

If you use go:generate to execute mockgen now, you can generate the config file by rewriting go:generate comment a little bit.

Replace from mockgen to gomockhandler -config=/path/to/gomockhandler.json in all go:generate comments, and run go generate ./... in your project. And then,

- //go:generate mockgen -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG
+ //go:generate gomockhandler -config=/path/to/gomockhandler.json -source=$GOFILE -destination=mock_$GOFILE -package=$GOPACKAG

After generating the config, your go:generate comments are no longer needed. You've been released from a slow-mockgen with go generate!

Let's delete all go:generate comments for mockgen in your project.

Recommendations

  • name the config file gomockhandler.json, and place it in a location where the gomockhandler is likely to be run frequently.
  • use Source Mode, if there is no great reason to use Reflect mode., which is much faster because the gomockhandler will skip processing if the source file has not been changed.

delete mocks to be generated from config

You can remove the mocks to be generated from the config.

gomockhandler -config=/path/to/gomockhandler.json -destination=./mock/user.go deletemock 

This command only delete the mock from the configuration. So please delete the mock file itself manually.

generate mock

You can generate all mocks from config.

gomockhandler -config=/path/to/gomockhandler.json mockgen

check if mock is up-to-date

You can check if the mock is generated based on the latest interface.

It is useful for ci.

gomockhandler -config=/path/to/gomockhandler.json check

If some mocks are not up to date, you can see the error and gomockhandler will exit with exit-code 1

2021/03/10 22:17:12 [WARN] mock is not up to date. source: ./interfaces/user.go, destination: ./interfaces/../mock/user.go
2021/03/10 22:17:12 mocks is not up-to-date

edit config manually

You can edit the config manually.

But, it is RECOMMENDED to use CLI, especially for adding/editing mocks. (This is because CLI will check if mockgen works correctly with that option, and then edit the config.)

The config json file has the following format.

{
	"mocks": {
		"mock/user.go": {
			"checksum": "qxZ/pLjLBtib7o+kDLOzOQ==",
			"source_checksum": "UUyR0gaRX4IbPPAttwOCXw==",
			"mode": "SOURCE_MODE",
			"source_mode_runner": {
				"source": "interfaces/user.go",
				"destination": "mock/user.go"
			}
		},
		"mock/user2.go": {
			"checksum": "qxZ/pLjLBtib7o+kDLOzOQ==",
			"source_checksum": "AAAAAAAAAAAAAAAAAAAAAA==",
			"mode": "REFLECT_MODE",
			"reflect_mode_runner": {
				"package_name": "playground/interfaces",
				"interfaces": "User2",
				"destination": "mock/user2.go"
			}
		}
	}
}

As mentioned above, there are two modes of mockgen, and the format of the config is slightly different depending on which mode you are using. In the ***mode-runner field, specify the option to be used when running mockgen.

In the checksum field, the checksum of the currently generated mock is stored. With this checksum, the gomockhandler checks if the mock is the same as the mock generated from the latest interface.

In the source_checksum field, the checksum of the currently generated mock's source file is stored. This field is only valid in source mode, and when reflect mode is used, the value will be AAAAAAAAAAAAAAAAAAAAAA==.

contributing

see CONTRIBUTING.md

gomockhandler's People

Contributors

0tarof avatar fsmiamoto avatar kno3a87 avatar riita10069 avatar s4s7 avatar sanposhiho avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

gomockhandler's Issues

Format json config

To make it easier to read json.
(In the future, it will not be necessary for users to look at the json directly.)

add -f flag

In Source mode, skip generation if the source file is not changed.

-f flag will not skip the generation of mocks.

the order on generated configuration is randomly changed

Currently if we do gomockhandler mockgen order of content randomly changed, although there is no changes.
For Example:

// before
{
	"mocks": {
		"a_mock.go": {
			"checksum": "xxxxxxxxxxx",
			"source_checksum": "aaaaaaaaaaaaa",
			"mode": "SOURCE_MODE",
			"source_mode_runner": {
				"source": "a.go",
				"destination": "a_mock.go",
				"package": "main"
			}
		},
		"b_mock.go": {
			"checksum": "yyyyyyyyyyyy",
			"source_checksum": "bbbbbbbbbbb",
			"mode": "SOURCE_MODE",
			"source_mode_runner": {
				"source": "b.go",
				"destination": "b_mock.go",
				"package": "main"
			}
		}
}
// after
{
	"mocks": {
		"b_mock.go": {
			"checksum": "yyyyyyyyyyyy",
			"source_checksum": "bbbbbbbbbbb",
			"mode": "SOURCE_MODE",
			"source_mode_runner": {
				"source": "b.go",
				"destination": "b_mock.go",
				"package": "main"
			}
		},
		"a_mock.go": {
			"checksum": "xxxxxxxxxxx",
			"source_checksum": "aaaaaaaaaaaaa",
			"mode": "SOURCE_MODE",
			"source_mode_runner": {
				"source": "a.go",
				"destination": "a_mock.go",
				"package": "main"
			}
		}
}

This behavior becomes some noise when we manage config file by git.
I recommend those contents to be dictionary order to avoid this problem.

I think the part below leads this phenomenon.

for v2Name, v2Value := range in.Mocks {

Thank you.

configuration file is not readable

Now, we support configuration gomockhandler.json.

And to add new mock on config, users have to execute cmd like this, and config for new mock will be added on gomockhandler.json.
gomockhandler -config=/path/to/gomockhandler.json -source=foo.go -destination=./mock/ [other mockgen options]

But, PR reviewers cannot see what command will be registered, and it makes PR review a little hard.

So, I want to add new optional configuration file or add information on config file to resolve this.

Specify excluded path(s)

Being able to specify paths ignored by gomockhandler could be useful.

For example, one of my projects has a vendor folder where code from an external repository is being stored. In that folder, there are mock files. Those are not managed by gomockhandler and therefore, gomockhandler check complains about it. Given that those files come from outside of my project, I don't think having gomockhandler managing them would be a good idea.

Eliminate the need to install mockgen

Let's eliminate the need to install mockgen.


We currently require users to install it. But, unexpected behaviors may occur due to differences in mockgen behavior depending on which mockgen the user has installed.
Ideally, we should generate mocks without using user-installed mockgen and we can achieve that if we can import mockgen.


But currently, almost all logic of mockgen cannot be imported, because it is placed in main package.
So, I propose to fork golang/mock, add changes to make it importable, and use the fork to import mockgen.

And, I raised the issue for golang/mock.
golang/mock#609

The checksum value of the tmp file and the gomockhandler.json got different When running the check command.

Version

Actual behavior

Despite the mock being up to date, the gomockhandler -config=./gomockhandler.json check command reports a different checksum value, leading to the determination that it is not the latest version.

[ERROR] mock is not up to date. destination: usecases/mock/xxx.go

Expected behavior

gomockhandler -config=./gomockhandler.json check command works correctly.

Why this issue occurred

uber-go/mock@2c718f2 was merged and is affecting gomockhandler, causing the check command to not work correctly.

Detail

The checksum values differ because the file paths for the destination specified in the comments within code A and code B are different.

code A : generated code by go.uber.org/mock/mockgen

// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/org/repo/api/usecases (interfaces: xxx)
//
// Generated by this command:
//
//      mockgen -destination=usecases/mock/xxx.go -package=usecases_mock github.com/org/repo/api/usecases xxx
//

code B : tmp file code to calculate checksum in this line

// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/org/repo/api/usecases (interfaces: xxx)
//
// Generated by this command:
//
//      mockgen -destination=usecases/mock/tmp_xxx.go -package=usecases_mock github.com/org/repo/api/usecases xxx
//

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.