moldable
builds precise interfaces from any package so you can plug in mockery
, gomock
, moq
, or any other mock tool you like.
Warning
moldable
is just an experiment. I built it to learn Go AST for another open source project that will take up most of my time.
It works well, but I am not sure lots of people really need it (to be honest). If you try it, feel free to open an issue and tell me how it went, good or bad.
![]() |
---|
Example: every exported AWS S3 struct becomes its own ready-to-use interface. |
Most mock generators need an interface to do anything. When a library only exposes concrete structs you must hand-write that interface and keep it in sync with every upstream change. moldable
creates it in one command and gets out of your way. After that you can use whatever mocking framework you like.
- One-command package processing: Processes entire packages in a single run. Every exported struct that carries methods is discovered automatically and turned into the corresponding interface.
- Single YAML control: Keeps every setting in one committed YAML file so you can generate many packages at once, choose output locations, decide how interfaces are named, and reproduce identical results on any machine.
- Official Go parser: Uses Go's standard
go/ast
andgo/types
packages, guaranteeing the generated file is always syntactically correct. - Exact method reproduction: Renders every method signature exactly as found in the source (parameter names, types, results, and variadic dots included).
- Full generics support: Type parameters on structs and methods are reproduced together with their constraints.
- Rich type preservation: Preserves type aliases, pointers, slices, maps, channels, embedded structs, and any nested combination of them.
- Automatic import block: Builds the correct import section and picks non-conflicting local aliases when the same base name comes from different packages.
- Native module loading: Relies on Go's package loader, so it respects
go.mod
boundaries, works with vendored code, Go workspaces, and private modules without extra flags. - Customisable output: Choose the package name for generated files, use template names like
{package}.generated.go
, add a suffix (Client
→ClientContract
), and place everything in a clean output directory tree.
Pick the flow that best fits your environment.
Note
Why a binary?
moldable
is built with the newest Go release so it can parse the newest language features. If the Go installation on your machine is older than the version declared in go.mod
, go install
will refuse to build it.
Pre-built binaries bypass that check and run on any OS/arch we ship.
- Grab the latest binary from the releases page.
- Extract and move the executable to any directory in your
$PATH
.
Warning
Requires a Go installation at least as new as the version declared in go.mod.
Install the latest tag:
go install github.com/nuvrel/moldable/cmd/moldable@latest
Pin to a specific version (recommended):
go install github.com/nuvrel/moldable/cmd/moldable@<tag>
Replace
<tag>
with the desired tag (i.e.v1.0.0
).
Check the result:
moldable version
-
Create a starter config
moldable init
-
Edit
moldable.yaml
Replace the example path with the package you want.
For instance, to generate interfaces for the AWS S3 service package:
packages: - path: github.com/aws/aws-sdk-go-v2/service/s3
Add more packages underneath if you need them.
Warning
The listed package must already be present in your module (i.e. go get
it first).
-
Generate interfaces
moldable
-
Use the generated files with any mock tool you like:
Re-run moldable
whenever the upstream code changes; imports and file lists are recalculated automatically.
The file moldable.yaml
is created by moldable init
command.
Use the template as-is or edit the values you need; then add at least one real package path.
---
# Output configuration for generated interface files
output:
# Directory where generated files will be written
dir: ./generated
# Package name for generated code (singular noun following Go conventions)
package: contract
# File naming pattern for generated files
# Uses {package} placeholder for the original package name
filename: "{package}.generated.go"
# Naming conventions for generated interfaces
naming:
# Suffix for interface names (e.g., "Contract" for "ClientContract")
suffix: Contract
# Packages to process
packages:
- path: github.com/example/package/foo
# Additional packages
# - path: github.com/example/package/bar
Here are the validation rules:
Field | Requirement |
---|---|
output.dir |
non-empty string |
output.package |
valid Go identifier |
output.filename |
must contain substring {package} |
output.naming.suffix |
letters, digits or _ only |
packages[].path |
non-empty import path |
duplicate package paths | rejected |
After editing, run moldable
again; imports and method sets are re-computed automatically.
MIT.
See the LICENSE file for the full text.