Skip to content

bug: test:isolated has 4 test failures due to mock.module() leaking between files #258

Description

@BYK

Description

Running bun run test:isolated produces 4 test failures in test/isolated/dsn/errors.test.ts because mock.module() in test/isolated/resolve-target.test.ts pollutes the module cache for subsequent test files.

Steps to Reproduce

# Fails — 4 tests break
bun run test:isolated
# 53 pass, 4 fail

# Passes — same file in isolation works fine
bun test test/isolated/dsn/errors.test.ts
# 17 pass, 0 fail

Failing tests (all in formatMultipleProjectsFooter describe block):

  1. formats footer with two projects
  2. formats footer with projects without detectedFrom
  3. formats footer with mixed detectedFrom presence
  4. handles many projects

Error pattern:

Expected to contain: "Found 2 Sentry projects:"
Received: "Found 2 projects"

Root Cause

Bun runs test files sequentially in one thread. The execution order is:

  1. test/isolated/resolve-target.test.ts runs first and calls:

    // Line 56-65
    mock.module("../../src/lib/dsn/index.js", () => ({
      // ...
      formatMultipleProjectsFooter: (projects: unknown[]) =>
        projects.length > 1
          ? `Found ${projects.length} projects`    // ← simplified mock, missing "Sentry"
          : "",
    }));
  2. test/isolated/dsn/errors.test.ts runs afterward and imports:

    // Line 4
    import { formatMultipleProjectsFooter } from "../../../src/lib/dsn/errors.js";
  3. Even though errors.test.ts imports from the direct source (dsn/errors.js) rather than the re-export (dsn/index.js), Bun's module cache has been poisoned by the mock.module() call. The mock's simplified formatMultipleProjectsFooter (returns "Found N projects") overrides the real implementation (returns "Found N Sentry projects:").

Proposed Fix

Several options:

Option 1: Clean up mocks in resolve-target.test.ts

Add afterAll cleanup to restore the original module:

import { afterAll } from "bun:test";

afterAll(() => {
  mock.restore();
});

Option 2: Move non-isolated tests out of test/isolated/

The formatMultipleProjectsFooter tests in errors.test.ts don't use mock.module() themselves — they test the real function directly. They could be moved to test/lib/dsn/errors.test.ts to avoid the polluted environment entirely.

Option 3: Re-import in each test

Use dynamic import() inside each test to get a fresh module reference, bypassing the cached mock.

Files

  • test/isolated/resolve-target.test.ts:56-65 — the mock.module() call that pollutes the cache
  • test/isolated/dsn/errors.test.ts:297-368 — the 4 failing test assertions
  • src/lib/dsn/errors.ts:153-168 — the real formatMultipleProjectsFooter implementation
  • src/lib/dsn/index.ts:42 — re-export of formatMultipleProjectsFooter

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions