Skip to content

Latest commit

 

History

History
138 lines (101 loc) · 6.43 KB

mockery-v3-migration.md

File metadata and controls

138 lines (101 loc) · 6.43 KB

Migrating from mockery v2 to v3

build/make/mocks.mk uses mockery v3. mockery v3 no longer supports CLI flags like --all --dir; everything is controlled via the configuration file. Therefore the configuration now belongs entirely to the repository: the makefiles only provide the tool and the make targets.

make mocks aborts with an error if no .mockery.yaml exists in the repository root.

Targets

Target Description
make mocks Generates the mocks configured in .mockery.yaml.
make mocks-init Creates a .mockery.yaml with our defaults. Refuses to overwrite an existing file.
make mocks-delete Deletes all Go files containing the header Code generated by mockery.

make mocks does not delete old mocks. To regenerate from scratch, run make mocks-delete mocks.

Migration steps

1. Update the makefiles

Update the makefiles to the version with mockery v3 support (make self-update). If your Makefile overrides the mocks target, remove that override. If it sets MOCKERY_VERSION to a v2 version or overrides MOCKERY_IGNORED, remove those as well. A leftover v2 MOCKERY_VERSION shows up as a failing checksum (sha256sum: WARNING: 1 computed checksum did NOT match), because the v2 archive is checked against the v3 checksum.

2. Create the configuration

There are two ways:

  • Start fresh: move the old .mockery.yaml away and run make mocks-init.
  • Translate the existing v2 configuration: run .bin/mockery migrate --config .mockery.yaml.
    • The result is written to .mockery_v3.yml. mockery v3 does not find this file name when looking up its configuration, so rename it to .mockery.yaml.
    • The command is "not comprehensive and likely has missing edge cases" according to the mockery documentation. replace-type is not translated at all.
    • It prints a table of deprecated keys. Go through it.

3. Review the configuration

Check these points by hand, even after mockery migrate:

  • Set filename to mocks_test.go. We generate one mock file per package. mockery migrate keeps the old one-file-per-interface pattern.

  • mockname is now called structname, outpkg is now called pkgname.

  • Remove with-expecter (always active in v3), testonly (the _test.go property now results from filename only), inpackage and keeptree.

  • exclude is now exclude-subpkg-regex, exclude-regex is now exclude-interface-regex, include-regex is now include-interface-regex.

  • boilerplate-file, mock-build-tags and unroll-variadic move below template-data.

  • Check whether your tests rely on unrolled variadic arguments. v2 unrolled them by default, v3 does not, and the template does not set it either. If tests use expectations like EXPECT().List(ctx, list, labels) for a variadic method, they compile, but fail at runtime with mock: Unexpected Method Call, because the mock passes the variadic arguments as one slice. In that case add:

    template-data:
      unroll-variadic: true
  • resolve-type-alias is always false in v3 (the v2 default was true).

  • Add vendor to exclude-subpkg-regex if the repository has a vendored vendor/ directory.

  • The packages: block is mandatory and must contain the module path of the repository (see go list -m).

The template build/make/mockery.yaml.tpl shows our defaults.

Go workspaces

In a repository with a go.work and several modules, use one .mockery.yaml in the repository root instead of one per module. It lists every module below packages:; mockery loads them through the workspace and still writes the mocks next to the interfaces in the respective module:

packages:
  github.com/cloudogu/maintenance-assets:
    config: {}
  github.com/cloudogu/warp-assets:
    config: {}

make mocks-init creates this block automatically from go list -m. Delete the per-module .mockery.yaml files and the custom mocks target that changed into each module directory.

4. Check the mock type names

The template sets structname: "{{.Mock}}{{.InterfaceName | firstUpper }}". It produces the same names as the usual v2 setting mockname: "{{.Mock}}{{.InterfaceName | camelcase }}", e.g. mockLocalDoguFetcher for the unexported interface localDoguFetcher and MockDependencyValidator for DependencyValidator.

5. Remove the old mocks

make mocks-delete

This step is mandatory: the old mock_*_test.go files declare the same types as the new mocks_test.go, so the package would no longer compile.

6. Generate the mocks

make mocks

7. Verify

Run the tests, review the diff and commit the new .mockery.yaml together with the generated mocks.

Alternative template: matryer

The template sets template: testify, which generates the mocks with EXPECT() that all our tests use. mockery v3 also provides the matryer template. It generates moq-style mocks: a struct with one func field per method and a list of recorded calls, without a dependency on testify:

Switching an existing package to matryer means rewriting all tests that use EXPECT(). The template can also be set per package, so new packages can use matryer while existing ones keep testify.

packages:
  github.com/cloudogu/my-module:
    config: {}
  github.com/cloudogu/my-module/newpackage:
    config:
      template: matryer

Configuration of mocks.mk

Variable Default Description
MOCKERY_VERSION v3.8.0 mockery version. Changing it also requires MOCKERY_SUM.
MOCKERY_URL release asset for linux/x86_64 Download URL of the release archive.
MOCKERY_SUM sha256 of the linux/x86_64 asset Checksum of the release archive (see checksum.txt of the release).

If the installed binary in .bin/mockery does not match MOCKERY_VERSION, it is downloaded again.