-
Notifications
You must be signed in to change notification settings - Fork 4
Adopt moq for test mock generation #249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- Add moq to mise.toml tools - Create internal/testutil/ package with documentation - Add mise generate task for running go generate - Document mock generation workflow in CLAUDE.md Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add go:generate directives and generate mocks for: - git.Operations (GitOperationsMock) - worktree.Operations (WorktreeOperationsMock) - mise.Operations (MiseOperationsMock) - zellij.SessionManager and Session - beads.CLI (BeadsCLIMock) and Reader (BeadsReaderMock) - github.ClientInterface (GitHubClientMock) - claude.Runner (ClaudeRunnerMock) - process.ProcessLister and ProcessKiller - task.ComplexityEstimator - linear.ClientInterface (LinearClientMock) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace testify/mock embedding with function-field pattern consistent with moq-generated mocks. Hand-written since moq doesn't support generic interfaces. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace hand-coded mockProcessLister and mockProcessKiller with moq-generated ProcessListerMock and ProcessKillerMock from testutil. Use external test package (process_test) to avoid import cycles between process and testutil. Move escapePattern test to internal test file since it tests an unexported function. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Split tests into external test package (planner_test.go) using testutil.ComplexityEstimatorMock, and internal test file (internal_test.go) for testing unexported functions like canAddToTask and ComputeInterTaskDeps. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace incomplete MockClient with LinearClientMock that implements full ClientInterface using function-field pattern. Kept tests in internal package due to import cycle (testutil imports linear). Mock is hand-written in same style as moq-generated mocks, consistent with cachemanager approach. Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Remove duplicate MockClientInterface, MockGitOperations, MockWorktreeOperations - Use moq-generated GitHubClientMock, GitOperationsMock, WorktreeOperationsMock - All tests continue to pass using shared mocks Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Test NewOperations returns valid implementation - Verify GitOperationsMock implements git.Operations interface - Test mock function field behavior for BranchExists, ValidateExistingBranch - Test mock call tracking for FetchPRRef, PushSetUpstream, Pull, Clone - Test nil function returns zero values Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Test parseWorktreeList parsing: empty, single, multiple worktrees - Test edge cases: detached HEAD, paths with spaces, branch slashes - Test mock interface compliance with worktree.Operations - Test mock function field behavior and call argument tracking - Split into internal (worktree_test.go) and external (mock_test.go) tests Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Test findConfigFile detection for all config file variants - Test config file priority order (.mise.toml before mise.toml etc) - Test IsManaged detection at both package and Operations level - Test mock interface compliance with mise.Operations - Test mock function field behavior for all methods - Test mock call tracking for HasTask, RunTask, Exec arguments Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Move CacheManagerMock from _test.go to exportable file - Test CacheManagerMock Get/Set/Flush behavior with function fields - Test cache hit/miss scenarios with BeadsWithDepsResult type - Test FlushCache handles nil cache gracefully - Test BeadsWithDepsResult.GetBead for existing and non-existing beads - Test DefaultClientConfig returns expected defaults - Document cache key generation behavior (sorted IDs joined by comma) Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add installation instructions for moq via mise and comprehensive testing best practices section including call tracking, nil function behavior, and compile-time interface verification examples. Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Generate mocks for OrchestratorSpawner, WorkDestroyer interfaces - Generate mock for feedback.Processor interface - Add comprehensive tests for control plane handlers: - HandleGitPushTask (93.8% coverage) - HandleSpawnOrchestratorTask (93.3% coverage) - HandleDestroyWorktreeTask (91.7% coverage) - HandlePRFeedbackTask (90% coverage) - HandleCreateWorktreeTask (partial) - Add tests for scheduler functions - Add tests for ProcessAllDueTasksWithControlPlane - Add tests for HandleTaskError - Control mocks kept local to avoid import cycle with work package - Update CLAUDE.md with new mock documentation Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Change directory permissions from 0755 to 0750 in mise_test.go (G301) - Remove unused MiseOperationsMock return value from setupControlPlane Co-Authored-By: Claude Opus 4.5 <[email protected]>
newhook
commented
Jan 30, 2026
newhook
commented
Jan 30, 2026
newhook
commented
Jan 30, 2026
Replace manual if/t.Error patterns with testify/require assertions across 19 test files for more readable and consistent test code: - require.NoError for error checks - require.Equal for value comparisons - require.True/False for boolean checks - require.Nil/NotNil for nil checks - require.Len for length checks - require.Contains for substring checks - require.NotPanics for panic-safe code paths Closes bead ac-t4vk.16 Co-Authored-By: Claude Opus 4.5 <[email protected]>
Instead of generating mocks in a central internal/testutil/ package, mocks are now generated in their respective package directories (e.g., git_mock.go in internal/git/). This makes mocks easier to find and follows Go conventions of keeping related code together. Changes: - Update all //go:generate directives to output mocks locally - Update all test files to import mocks from their packages - Remove internal/testutil/ package (now empty) - Update CLAUDE.md documentation with new mock locations Co-Authored-By: Claude Opus 4.5 <[email protected]>
These tests were testing the moq library itself rather than project code. The mock behavior is already tested by moq's maintainers. Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Summary
This PR standardizes test mocking across the codebase by adopting moq for mock generation. It replaces hand-coded mocks and testify/mock-based mocks with a unified moq-generated approach, and modernizes all tests to use testify assertions.
Key improvements:
mise run generatetask for regenerating mocksrequire/assert), removing ~700 lines of verbose error handlingChanges
Infrastructure
mise.toml(go:github.com/matryer/moq)mise run generatetask forgo generate ./...internal/testutil/package—mocks now live alongside their interfacesGenerated Mocks (13 interfaces)
Mocks are co-located with their interfaces in each package:
Test Modernization
require/assertinstead of manualif err != nilcheckssetupControlPlanehelper to return a struct instead of multiple valuesConverted Tests
internal/beads/cachemanager/- Removed testify/mock dependencyinternal/process/- Converted hand-coded mocksinternal/task/planner_test.go- Converted hand-coded mocksinternal/linear/fetcher_test.go- Converted function-field mocksinternal/work/import_pr_test.go- Consolidated local mocks into package mocksNew Test Coverage
internal/git/git_test.go- Tests for git operationsinternal/worktree/worktree_test.go- Tests for worktree operationsinternal/mise/mise_test.go- Tests for mise tool managementinternal/beads/client_test.go- Tests for beads client cachinginternal/control/control_test.go- Comprehensive control plane testsBeads Resolved
Stats
Net effect: ~6000 lines added (mostly new tests and generated mocks)
Test Plan
go test ./...)mise run generategolangci-lint run)Usage
To regenerate mocks after interface changes:
To add a new mock, add a
//go:generatedirective to the interface file://go:generate moq -stub -out mypkg_mock.go . InterfaceName:InterfaceNameMock🤖 Generated with Claude Code