go-crypto-wallet / internal
Cursor rule128 starsChanged 6 months agoMITView on GitHub
Mockery Mock Generation Rules
We split this mockery.mdc into the rules it gives an agent
8 rules. About 0 are common, 3 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈3
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 12
Every interface defined under internal/application/ports/ MUST have a corresponding mockery-generated mock in the appropriate mocks/ …
- Very specific: line 33
When a new interface is added to internal/application/ports/:
- Very specific: line 37
Verify: Run make go-lint and make check-build.
- Distinctive: line 39
Do these in the same commit or PR as the interface definition.
- Very specific: line 76
Never: call mock.AssertExpectations(t) manually — the NewMock*(t) constructor registers cleanup automatically via t.Cleanup.
- Very specific: line 82
Always regenerate with make mockery instead of editing manually.
- Distinctive: line 86
When a use case declares a local unexported interface that composes two (or more) port interfaces (e.g.
- Distinctive: line 117
Do not generate a mock for the composite local interface itself
≈ “Common” is an estimate: at least 1 in 5 of the 6,350 Cursor rule files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
---
description: Mockery Mock Generation Rules
globs: ["internal/application/ports/**/*.go", "internal/infrastructure/**/*.go"]
alwaysApply: false
---
# Mockery Mock Generation Rules
## Overview
Every interface defined under `internal/application/ports/` MUST have a corresponding
mockery-generated mock in the appropriate `mocks/` subdirectory of the infrastructure layer.
Manually written mocks or stubs for these interfaces are **not allowed**.
## Placement Convention
Mocks are placed in the infrastructure layer alongside the concrete implementations:
| Interface package (`application/ports/`) | Mock 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/`
## Mandatory Steps When Adding a New Interface
When a new interface is added to `internal/application/ports/`:
1. **Add to `.mockery.yaml`**: Register the interface under its package entry with the correct `dir`.
2. **Run `make mockery`**: Regenerate all mocks.
3. **Verify**: Run `make go-lint` and `make check-build`.
Do these in the **same commit or PR** as the interface definition.
## `.mockery.yaml` Entry Format
```yaml
packages:
github.com/hiromaily/go-crypto-wallet/internal/application/ports/<layer>/<pkg>:
config:
dir: "internal/infrastructure/<layer>/<pkg>/mocks"
pkgname: "mocks"
interfaces:
MyNewInterface:
```
## Mock File Conventions (auto-applied by global config)
| Setting | Value |
|---|---|
| Filename | `mock_<interface_name_snakecase>.go` |
| Struct name | `Mock<InterfaceName>` |
| Constructor | `NewMock<InterfaceName>(t)` |
| Framework | `testify/mock` with `.EXPECT()` builder |
## Using Mocks in Tests
```go
import coldmocks "github.com/hiromaily/go-crypto-wallet/internal/infrastructure/repository/cold/mocks"
func TestFoo(t *testing.T) {
repo := coldmocks.NewMockBTCAccountKeyRepositorier(t)
repo.EXPECT().
GetOneMaxID(domainAccount.AccountTypeDeposit).
Return(key, nil)
// ...
}
```
**Never** call `mock.AssertExpectations(t)` manually — the `NewMock*(t)` constructor registers
cleanup automatically via `t.Cleanup`.
## DO NOT Edit Generated Mock Files
Files in `mocks/` directories contain `// Code generated by mockery; DO NOT EDIT.`.
Always regenerate with `make mockery` instead of editing manually.
## Combined Mock Struct for Local Unexported Interfaces
When a use case declares a local unexported interface that composes two (or more) port interfaces
(e.g. `xrpSendTxClient` combining `TransactionSubmitter` + `LedgerPoller`), tests cannot directly
use a single generated mock because no single mock satisfies the composite type.
**Pattern**: embed the relevant mocks into a thin struct:
```go
// Production code (send_transaction.go)
type xrpSendTxClient interface {
apixrp.TransactionSubmitter
apixrp.LedgerPoller
}
// Test code (send_transaction_test.go)
type mockSendTxClient struct {
*xrpapiamocks.MockTransactionSubmitter
*xrpapiamocks.MockLedgerPoller
}
func createSendUseCase(deps *sendTestDependencies) watchusecase.SendTransactionUseCase {
client := &mockSendTxClient{
MockTransactionSubmitter: deps.submitter,
MockLedgerPoller: deps.ledgerPoller,
}
return xrp.NewSendTransactionUseCase(client, nil, deps.txDetailRepo, deps.txFileRepo)
}
```
Rules:
- The embedding struct lives in the **test file**, not in `mocks/`
- Each embedded field is still a `NewMock*(t)` instance with its own `.EXPECT()` setup
- Do **not** generate a mock for the composite local interface itself
## Exceptions
- **`Ethereumer` (ETH)**: DI-layer-only monolithic interface — do NOT add to `.mockery.yaml`.
- **`ETHTransactionSender`**: Type alias for `TxSender` — mockery cannot generate mocks for type aliases; mock `TxSender` instead.
- **Composed ETH interfaces** (`ETHKeygenSignClient`, `ETHWatchClient`, `WatchTxCreationDeps`, `KeygenSignTxDeps`): Leaf interface mocks satisfy all compositions implicitly — do NOT add composed interfaces to `.mockery.yaml`.
- **Use case interfaces** (`internal/application/usecase/*/interfaces.go`): These are NOT ports interfaces. Simple struct stubs are acceptable for testing use case orchestration.
- **Compile-time conformance stubs** in `*_test.go` files (e.g., in `ports/` packages): These are intentional type-check helpers, not test doubles — keep them as-is.
## Related Files
- `.mockery.yaml` — mockery configuration (SSOT for all mock generation)
- `Makefile` → `make mockery` — regenerates all mocks
- `@.claude/rules/internal/infrastructure-layer.md` — infrastructure layer rules
- `@.claude/rules/internal/application-layer.md` — application layer rules
Where files are headingNew Cursor rule files have more rules about planning and tracking tasks, and fewer about code style.
Of the Cursor rule files we read, the 3,978 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository62 other files it gives its agents.
- AGENTS.mdAGENTS.md
- internal/AGENTS.mdAGENTS.md
- pkg/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- internal/CLAUDE.mdCLAUDE.md
- pkg/CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/agent-files.mdcCursor rule
- .cursor/rules/apps/bun.mdcCursor rule
- .cursor/rules/apps/eth-contracts.mdcCursor rule
- .cursor/rules/apps/xrp-server.mdcCursor rule
- .cursor/rules/database/atlas-hcl.mdcCursor rule
- .cursor/rules/database/sqlc.mdcCursor rule
- .cursor/rules/documentation-language.mdcCursor rule
- .cursor/rules/general.mdcCursor rule
- .cursor/rules/github-actions.mdcCursor rule
- .cursor/rules/go/conventions.mdcCursor rule
- .cursor/rules/go/di.mdcCursor rule
- .cursor/rules/go/go-path.mdcCursor rule
- .cursor/rules/go/go-test.mdcCursor rule
- .cursor/rules/internal/application-layer.mdcCursor rule
- .cursor/rules/internal/btc-shared.mdcCursor rule
- .cursor/rules/internal/clean-architecture.mdcCursor rule
- .cursor/rules/internal/cli-structure.mdcCursor rule
- .cursor/rules/internal/domain-layer.mdcCursor rule
- .cursor/rules/internal/dto.mdcCursor rule
- .cursor/rules/internal/infrastructure-layer.mdcCursor rule
- .cursor/rules/internal/interface-adapters-layer.mdcCursor rule
- .cursor/rules/internal/internal-interface.mdcCursor rule
- .cursor/rules/internal/repository.mdcCursor rule
- .cursor/rules/internal/usecase.mdcCursor rule
- .cursor/rules/proto.mdcCursor rule
- .cursor/rules/README.mdCursor rule
- .cursor/rules/security.mdcCursor rule
- .cursor/rules/shell-script.mdcCursor rule
- .cursor/rules/ssot.mdcCursor rule
- .cursor/rules/task-context-loading.mdcCursor rule
- .cursor/rules/typescript.mdcCursor rule
- .cursor/rules/yaml.mdcCursor rule
- llms.txtllms.txt
- bch-developmentSkill
- btc-terminologySkill
- db-migrationSkill
- devopsSkill
- docs-ssotSkill
- docs-updateSkill
- fix-pr-reviewSkill
- github-issue-creationSkill
- git-workflowSkill
- go-developmentSkill
- knowledge-gapSkill
- label-context-mappingSkill
- makefile-updateSkill
- mockerySkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- shell-scriptsSkill
- solidity-developmentSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

