BUCKYVERSE

This guide outlines the process for migrating test mocks from the Mox framework to the Patch framework within the Codexis project.

1. Introduction & Rationale

The primary goal of this migration is to standardize our mocking approach on the Patch library, moving away from Mox. This decision is in line with Architectural Decision Record (ADR) 0030, which identified Patch as the preferred mocking library for its benefits in terms of API simplicity, lexical scoping of mocks, and improved maintainability.

Benefits of Migrating to Patch:

2. Key Differences: Mox vs. Patch

Feature Mox Patch
Mock Definition Requires Mox.defmock/2 for a behaviour. No explicit mock definition; functions are patched directly.
Scoping Global or per-process via set_mox_global Lexically scoped to with_mocked_function/3 or Patch.instead/3 block.
Expect vs. Stub Distinct expect (verified) & stub. No direct distinction; behavior is defined, verification is separate.
Verification Mox.verify!/1 or Mox.verify_once!/1. Assertions within mock function, or assert_received if using messages.
Compile Checks Relies on behaviour for contract. Patch.instead/3 provides compile-time arity/existence checks.

3. Migration Patterns

These patterns are based on common Mox usage and their equivalents in Patch, largely derived from test/support/patch_example.exs.

3.1. Mox.expect / Mox.stub (Mocking a function with a specific implementation)

3.2. Mox.verify! (Verifying a mock was called / Verifying arguments)

3.3. Mocking a function that raises an exception

4. Step-by-Step Migration Process for a Test File

  1. Remove Mox Imports/Setup:

    • Delete import Mox.
    • Remove any Mox.defmock calls related to the test, typically found in test/support/mocks.ex or directly in the test file for local mocks.
    • Remove Mox-specific setup like setup :verify_on_exit! or setup :set_mox_global.
  2. Import Patch:

    • Add import Patch at the top of your test file.
  3. Convert Mock Usage:

    • Replace Mox.expect/3 or Mox.stub/3 calls with Patch.with_mocked_function/3.
    • Ensure the code that relies on the mock is inside the do...end block of with_mocked_function.
  4. Adapt Verification Logic:

    • If Mox.verify!/1 was used, convert this to assertions within the mock function's body (if checking arguments) or use assert_received if you were primarily ensuring the mock was called.
    • Assert the expected outcome of the function under test.
  5. Run Tests:

    • Execute your tests to ensure they pass and the behavior remains identical.

5. Common Pitfalls & Troubleshooting

6. Patch-Specific Features & Best Practices

7. FAQ


This guide provides a starting point for migration. Always refer to the official Patch documentation for the most detailed and up-to-date information.