Skip to content

MongoDB Transactions Fail in Tests: MongoMemoryServer Needs Replica Set Configuration #489

@seanspeaks

Description

@seanspeaks

Problem

Tests are failing with MongoDB transaction errors when using Prisma operations:

PrismaClientKnownRequestError: 
Invalid `prisma.credential.deleteMany()` invocation

Raw query failed. Code: `unknown`. 
Message: `Kind: Transactions are not supported by this deployment, labels: {}`

Root Cause

MongoDB requires a replica set to support transactions. Our test setup uses mongodb-memory-server (standalone mode) which doesn't support transactions by default.

Current Setup (packages/test/mongodb.js):

async start() {
    this.#mongoServer = await MongoMemoryServer.create();
    process.env.MONGO_URI = this.#mongoServer.getUri();
}

This creates a standalone MongoDB instance which doesn't support:

  • Multi-document transactions
  • $transaction operations
  • Prisma's automatic transaction wrapping for batch operations

Why This Matters

  1. Prisma automatically wraps batch operations in transactions:

    • deleteMany(), updateMany(), createMany()
    • Operations within Prisma Client Extensions (like our encryption extension)
  2. Tests fail that use legitimate Prisma patterns:

    // This fails in tests but works in production
    await prisma.credential.deleteMany({ 
        where: { externalId: { startsWith: 'test-' } } 
    });
  3. Production uses MongoDB with replica sets (AWS DocumentDB, MongoDB Atlas)

    • Tests don't match production environment
    • False confidence in test suite

Migration Context

We're in the middle of migrating from Mongoose to Prisma:

  • Old code: Uses Mongoose models and connections
  • New code: Uses Prisma client with field-level encryption
  • Hybrid state: Both systems coexist, causing conflicts

Evidence of migration in progress:

  • packages/core/database/mongoose.js - Legacy Mongoose setup
  • packages/core/database/prisma.js - New Prisma client
  • packages/core/database/models/ - Old Mongoose models still in use
  • packages/core/database/repositories/health-check-repository-mongodb.js - Uses mongoose.connection

Affected Test Files

Tests using Prisma with batch operations fail:

  • database/encryption/encryption-integration.test.js - All cleanup operations
  • database/encryption/mongo-decryption-fix-verification.test.js
  • database/encryption/postgres-decryption-fix-verification.test.js
  • user/tests/user-password-encryption-isolation.test.js

Solution

Option 1: Enable Replica Set in MongoMemoryServer (Recommended)

Update packages/test/mongodb.js:

const { MongoMemoryReplSet } = require('mongodb-memory-server');

class TestMongo {
    #mongoServer;

    async start() {
        // Create replica set instead of standalone
        this.#mongoServer = await MongoMemoryReplSet.create({
            replSet: { 
                count: 1,  // Single node replica set (sufficient for tests)
                storageEngine: 'wiredTiger'
            }
        });
        
        const uri = this.#mongoServer.getUri();
        process.env.MONGO_URI = uri;
        
        console.log('Started in-memory MongoDB replica set', uri);
    }

    async stop() {
        await this.#mongoServer.stop();
        process.env.MONGO_URI = undefined;
        this.#mongoServer = undefined;
    }
}

Benefits:

  • Enables transaction support
  • Better matches production environment
  • Fixes all Prisma batch operation tests
  • No changes needed to test code

Option 2: Disable Prisma Transactions in Tests (Not Recommended)

Configure Prisma to skip transactions:

// Not ideal - tests wouldn't match production behavior
const prisma = new PrismaClient({
    transactionOptions: {
        maxWait: 5000,
        timeout: 10000,
        isolationLevel: 'ReadUncommitted'
    }
});

This doesn't actually disable transactions, just configures them differently.

Additional Work: Complete Mongoose → Prisma Migration

While fixing the test setup, we should complete the migration:

Current Hybrid State Issues:

  1. Two database clients initialized (mongoose + prisma)
  2. Connection state checks use Mongoose (mongoose.connection.readyState)
  3. Schema initialization uses Mongoose (ensureCollectionsExist)
  4. Legacy models in database/models/ still imported

Complete Migration Tasks:

  • Replace all mongoose.connection.* with Prisma equivalents
  • Remove database/mongoose.js and legacy connection logic
  • Migrate database/models/*.js Mongoose models to Prisma schema
  • Update health-check-repository-mongodb.js to use Prisma connection checks
  • Remove Mongoose dependency from package.json once fully migrated
  • Update mongodb-schema-init.js to use Prisma schema inspection instead of Mongoose

Benefits of Completing Migration:

  • Single source of truth for database operations
  • Consistent encryption across all models
  • Better type safety with Prisma
  • Reduced complexity (no dual connection management)
  • Modern ORM patterns and tooling

Testing the Fix

After implementing Option 1:

# Should pass all encryption tests
npm test -- database/encryption/

# Verify transaction support
npm test -- database/encryption/encryption-integration.test.js

# Check cleanup operations work
npm test -- user/tests/user-password-encryption-isolation.test.js

References

Related Files

Test Infrastructure:

  • packages/test/mongodb.js - MongoMemoryServer setup (needs replica set)
  • packages/test/jest-global-setup.js - Jest test setup
  • packages/core/jest-setup.js - Core package test setup

Affected by Mongoose/Prisma Hybrid:

  • packages/core/database/prisma.js - Prisma client with encryption
  • packages/core/database/mongoose.js - Legacy Mongoose connection
  • packages/core/database/utils/mongodb-schema-init.js - Uses Mongoose connection
  • packages/core/database/repositories/health-check-repository-mongodb.js - Uses Mongoose

Priority: High - Blocking test suite reliability
Category: Testing Infrastructure, Database Migration
Affects: All Prisma-based tests using batch operations

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdependenciesUpdate one or more dependencies versionmajorIncrement the major version when mergedtestsAdd or improve existing tests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions