mockery

Mock generation workflow for go-crypto-wallet. Activate whenever a developer asks to generate a mock for a new interface, add test coverage that requires a mock, or replace a manually-written test stub for a ports interface. Claude MUST use `make mockery` — never write mock struct code by hand.

125 stars

Best use case

mockery is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Mock generation workflow for go-crypto-wallet. Activate whenever a developer asks to generate a mock for a new interface, add test coverage that requires a mock, or replace a manually-written test stub for a ports interface. Claude MUST use `make mockery` — never write mock struct code by hand.

Teams using mockery should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/mockery/SKILL.md --create-dirs "https://raw.githubusercontent.com/hiromaily/go-crypto-wallet/main/.claude/skills/mockery/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/mockery/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How mockery Compares

Feature / AgentmockeryStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Mock generation workflow for go-crypto-wallet. Activate whenever a developer asks to generate a mock for a new interface, add test coverage that requires a mock, or replace a manually-written test stub for a ports interface. Claude MUST use `make mockery` — never write mock struct code by hand.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

# Mockery Mock Generation Workflow

## When to Activate This Skill

- A new interface is added to `internal/application/ports/`
- A test file contains a manually-written mock/stub for a ports interface
- A developer asks to add mock coverage for an existing ports interface
- A test needs to replace `On(...).Return(...)` setup on a hand-rolled struct with generated mock expectations

## Placement Convention

Mocks live in the infrastructure layer, beside the concrete implementations:

| Interface package (`application/ports/`) | Mock output directory (`infrastructure/`)        |
| ---------------------------------------- | ------------------------------------------------ |
| `ports/api/btc/`                         | `infrastructure/api/btc/mocks/`                  |
| `ports/api/eth/`                         | `infrastructure/api/eth/mocks/`                  |
| `ports/api/xrp/`                         | `infrastructure/api/xrp/mocks/`                  |
| `ports/file/`                            | `infrastructure/storage/file/transaction/mocks/` |
| `ports/repository/cold/`                 | `infrastructure/repository/cold/mocks/`          |
| `ports/repository/watch/`                | `infrastructure/repository/watch/mocks/`         |

**Pattern**: `ports/<layer>/<pkg>/` → `infrastructure/<layer>/<pkg>/mocks/`

## Step-by-Step Workflow

1. **Locate the interface** — find the Go file in `internal/application/ports/` that defines the interface.
2. **Determine the target directory** — use the placement convention table above to identify the `dir` value.
3. **Add or update `.mockery.yaml`** — append the interface name under its package entry (or add a new package entry if none exists). See the template below.
4. **Run `make mockery`** — regenerates all mocks in one pass. Never create or edit mock files manually.
5. **Verify** — run `make go-lint` and `make check-build` to confirm the generated code compiles cleanly.
6. **Update tests** — replace any manual stub usage with `NewMock*(t)` + `.EXPECT()` builder calls.

## `.mockery.yaml` Entry Template

### Adding an interface to an existing package entry

```yaml
packages:
  github.com/hiromaily/go-crypto-wallet/internal/application/ports/<layer>/<pkg>:
    config:
      dir: "internal/infrastructure/<layer>/<pkg>/mocks"
      pkgname: "mocks"
    interfaces:
      ExistingInterface:
      MyNewInterface: # ← append here
```

### Adding a brand-new package entry

```yaml
github.com/hiromaily/go-crypto-wallet/internal/application/ports/<layer>/<pkg>:
  config:
    dir: "internal/infrastructure/<layer>/<pkg>/mocks"
    pkgname: "mocks"
  interfaces:
    MyNewInterface:
```

The global settings (`filename`, `structname`, `template`, `formatter`) are already configured in `.mockery.yaml` and apply automatically — do **not** override them per-package.

## Generated File Conventions

| Setting     | Value                                        |
| ----------- | -------------------------------------------- |
| Filename    | `mock_<interface_name_snakecase>.go`         |
| Struct name | `Mock<InterfaceName>`                        |
| Constructor | `NewMock<InterfaceName>(t)`                  |
| Package     | `mocks`                                      |
| Header      | `// Code generated by mockery; DO NOT EDIT.` |

## Test Usage — Before / After

### Before (manual stub — do NOT write this)

```go
// ❌ Manually-written stub in a test file
type stubAccountRepo struct{}

func (s *stubAccountRepo) GetOneMaxID(accountType domainAccount.AccountType) (*domainKey.BTCAccountKey, error) {
    return &domainKey.BTCAccountKey{Index: 0}, nil
}

func TestFoo(t *testing.T) {
    repo := &stubAccountRepo{}
    uc := NewUseCase(repo)
    // ...
    // Manual assertion:
    // (no automatic call-count verification)
}
```

### After (mockery-generated mock — always use this)

```go
// ✅ Import the generated mocks package
import coldmocks "github.com/hiromaily/go-crypto-wallet/internal/infrastructure/repository/cold/mocks"

func TestFoo(t *testing.T) {
    repo := coldmocks.NewMockBTCAccountKeyRepositorier(t) // registers cleanup automatically
    repo.EXPECT().
        GetOneMaxID(domainAccount.AccountTypeDeposit).
        Return(&domainKey.BTCAccountKey{Index: 0}, nil)

    uc := NewUseCase(repo)
    // ...
    // AssertExpectations is called automatically via t.Cleanup — do NOT call it manually
}
```

Key differences:

- `NewMock*(t)` registers `t.Cleanup(func() { mock.AssertExpectations(t) })` automatically — never call `AssertExpectations` manually.
- `.EXPECT().Method(args...).Return(values...)` provides type-safe, call-count-verified expectations.
- The generated mock handles all type assertions internally — no `args.Get(0).(*Type)` boilerplate.

## Exceptions — Do NOT Add to `.mockery.yaml`

| Type                                                                     | Reason                                                                                                  |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| `Ethereumer` (ETH)                                                       | DI-layer-only monolithic interface; not consumed by use cases                                           |
| `ETHTransactionSender`                                                   | Type alias for `TxSender`; mockery cannot generate mocks for type aliases — use `TxSender` mock instead |
| Use case interfaces (`internal/application/usecase/*/interfaces.go`)     | These are not ports interfaces; simple struct stubs are acceptable for testing use case orchestration   |
| Composed/aggregate interfaces (`Bitcoiner`, `ETHKeygenSignClient`, etc.) | Leaf interface mocks satisfy all compositions — add only the leaf interfaces that use cases depend on   |
| Compile-time conformance stubs in `*_test.go` under `ports/`             | Intentional type-check helpers, not test doubles — leave them as-is                                     |

## Verification Commands

```bash
make mockery        # Regenerate all mocks after .mockery.yaml changes
make go-lint        # Required: zero lint errors
make check-build    # Required: full build succeeds
make go-test         # Recommended: run tests for affected packages
```

## Related Files

- `.mockery.yaml` — SSOT for all mock generation configuration
- `.claude/rules/internal/mockery.md` — project rules enforcing this convention
- `.claude/rules/internal/infrastructure-layer.md` — infrastructure layer rules
- `.claude/rules/internal/application-layer.md` — application layer rules

Related Skills

wallet-cli

125
from hiromaily/go-crypto-wallet

How to run watch, keygen, and sign wallet CLI commands. Use when executing wallet commands or testing wallet functionality.

typescript-development

125
from hiromaily/go-crypto-wallet

TypeScript/JavaScript development workflow for apps/ directory. Use when modifying TypeScript code in xrpl-grpc-server or JavaScript in eth-contracts.

solidity-development

125
from hiromaily/go-crypto-wallet

Solidity smart contract development workflow. Use when modifying smart contracts in apps/eth-contracts/contracts/.

shell-scripts

125
from hiromaily/go-crypto-wallet

Shell script development workflow. Use when modifying files in scripts/ directory or any *.sh files.

openspec-propose

125
from hiromaily/go-crypto-wallet

Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.

openspec-explore

125
from hiromaily/go-crypto-wallet

Enter explore mode - a thinking partner for exploring ideas, investigating problems, and clarifying requirements. Use when the user wants to think through something before or during a change.

openspec-archive-change

125
from hiromaily/go-crypto-wallet

Archive a completed change in the experimental workflow. Use when the user wants to finalize and archive a change after implementation is complete.

openspec-apply-change

125
from hiromaily/go-crypto-wallet

Implement tasks from an OpenSpec change. Use when the user wants to start implementing, continue implementation, or work through tasks.

makefile-update

125
from hiromaily/go-crypto-wallet

Makefile development workflow. Use when modifying Makefile or files in make/ directory.

label-context-mapping

125
from hiromaily/go-crypto-wallet

Maps GitHub labels to Skills and Context documents. Use when creating issues (github-issue-creation) or working on issues (fix-issue command).

knowledge-gap

125
from hiromaily/go-crypto-wallet

Post-task knowledge gap review and proposals for improving skills/rules

go-development

125
from hiromaily/go-crypto-wallet

Go development workflow including verification commands and self-review checklist. Use when modifying Go code in internal/, pkg/, or cmd/ directories.