From db-mongodb
Use when writing tests for MongoDB code — Jest with mongodb-memory-server for Node.js, pytest with mongomock for Python, .NET integration tests with test containers, and seed data management
How this skill is triggered — by the user, by Claude, or both
Slash command
/db-mongodb:mongodb-testingThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
```javascript
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongoose = require('mongoose');
const Order = require('../models/Order');
let mongoServer;
beforeAll(async () => {
mongoServer = await MongoMemoryServer.create();
await mongoose.connect(mongoServer.getUri());
});
afterAll(async () => {
await mongoose.disconnect();
await mongoServer.stop();
});
afterEach(async () => {
await Order.deleteMany({});
});
describe('Order Model', () => {
it('should create order with valid data', async () => {
const order = await Order.create({
customerId: new mongoose.Types.ObjectId(),
items: [{ productId: new mongoose.Types.ObjectId(), name: 'Widget', quantity: 2, price: 10.00 }],
status: 'pending',
total: 20.00,
createdBy: 'test'
});
expect(order._id).toBeDefined();
expect(order.status).toBe('pending');
expect(order.items).toHaveLength(1);
});
it('should reject order without items', async () => {
await expect(Order.create({
customerId: new mongoose.Types.ObjectId(),
items: [],
status: 'pending',
total: 0,
createdBy: 'test'
})).rejects.toThrow();
});
});
import pytest
import mongomock
from pymongo import MongoClient
@pytest.fixture
def db():
client = mongomock.MongoClient()
db = client.testdb
yield db
client.close()
def test_create_order(db):
order = {
"customerId": "customer123",
"items": [{"productId": "prod1", "name": "Widget", "quantity": 2, "price": 10.00}],
"status": "pending",
"total": 20.00,
}
result = db.orders.insert_one(order)
assert result.inserted_id is not None
found = db.orders.find_one({"_id": result.inserted_id})
assert found["status"] == "pending"
assert len(found["items"]) == 1
def test_aggregation_pipeline(db):
db.orders.insert_many([
{"customerId": "c1", "total": 100, "status": "confirmed"},
{"customerId": "c1", "total": 200, "status": "confirmed"},
{"customerId": "c2", "total": 150, "status": "confirmed"},
])
pipeline = [
{"$match": {"status": "confirmed"}},
{"$group": {"_id": "$customerId", "totalSpent": {"$sum": "$total"}}},
{"$sort": {"totalSpent": -1}},
]
results = list(db.orders.aggregate(pipeline))
assert results[0]["_id"] == "c1"
assert results[0]["totalSpent"] == 300
public class OrderRepositoryTests : IAsyncLifetime
{
private MongoDbRunner _runner;
private IMongoDatabase _database;
public async Task InitializeAsync()
{
_runner = MongoDbRunner.Start();
var client = new MongoClient(_runner.ConnectionString);
_database = client.GetDatabase("testdb");
}
public async Task DisposeAsync()
{
_runner.Dispose();
}
[Fact]
public async Task GetById_ReturnsOrder_WhenExists()
{
var repo = new OrderRepository(_database);
var order = new Order { CustomerId = "c1", Total = 100m, Status = OrderStatus.Pending };
await repo.CreateAsync(order);
var result = await repo.GetByIdAsync(order.Id);
result.Should().NotBeNull();
result!.CustomerId.Should().Be("c1");
}
}
testdata/ directorydb.collection.insertMany(fixtures)afterEach / teardown, not beforeEachObjectId deterministic generation for reproducible IDs in testsdescribe("OrderRepository", () => {
it("positive: should insert order with valid data", async () => {
const order = { customerId: "c1", items: [{ productId: "p1", qty: 2 }], status: "pending" };
const result = await collection.insertOne(order);
expect(result.acknowledged).toBe(true);
const saved = await collection.findOne({ _id: result.insertedId });
expect(saved?.customerId).toBe("c1");
});
});
describe("OrderRepository", () => {
it("negative: should reject order without required customerId", async () => {
const order = { items: [{ productId: "p1", qty: 2 }] };
await expect(collection.insertOne(order)).rejects.toThrow(/validation/i);
});
it("negative: should reject duplicate order ID", async () => {
const order = { _id: new ObjectId("507f1f77bcf86cd799439011"), customerId: "c1" };
await collection.insertOne(order);
await expect(collection.insertOne(order)).rejects.toThrow(/duplicate key/i);
});
});
describe("OrderRepository", () => {
it("edge: should return empty array for query with no matches", async () => {
const results = await collection.find({ customerId: "nonexistent" }).toArray();
expect(results).toEqual([]);
});
it("edge: should handle document near max BSON size", async () => {
const largeValue = "x".repeat(15 * 1024 * 1024);
await expect(
collection.insertOne({ customerId: "c1", data: largeValue })
).rejects.toThrow();
});
});
describe("OrderRepository — security", () => {
it("security: should prevent NoSQL injection via $gt operator", async () => {
await collection.insertOne({ customerId: "c1", secret: "admin-token" });
const maliciousQuery = { customerId: { $gt: "" } };
const results = await orderRepo.findByCustomerId(maliciousQuery as any);
expect(results).toEqual([]);
});
it("security: should not expose internal fields in query errors", async () => {
try {
await collection.find({ $invalidOp: true } as any).toArray();
} catch (err: any) {
expect(err.message).not.toContain("connection string");
expect(err.message).not.toContain("password");
}
});
});
pytest:
def test_security_nosql_injection_prevented(mongo_collection):
mongo_collection.insert_one({"customer_id": "c1", "secret": "token"})
malicious = {"$gt": ""}
results = list(repo.find_by_customer_id(malicious))
assert results == []
npx claudepluginhub gagandeepp/software-agent-teams --plugin db-mongodbGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.