Skip to content

Commit da83292

Browse files
authored
test(mongodb): verify User schema behaviors under connection state 99 (JhaSourav07#2031)
2 parents bdd82f5 + 1082bba commit da83292

1 file changed

Lines changed: 34 additions & 13 deletions

File tree

models/User.test.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,42 +90,34 @@ describe('User Model', () => {
9090

9191
expect(mongoose.connection.readyState).toBe(2);
9292
expect(operationAttempted).toBe(true);
93-
// Critical: result is 'buffered' not an error — distinguishes state 2 from state 0
9493
expect(result).toBe('buffered');
9594

96-
// 5. Cleanup
9795
readyStateSpy.mockRestore();
9896
});
9997
});
10098

10199
describe('Database Connection State 0 Handling', () => {
102100
it('fails queries gracefully with a ConnectionError when disconnected', async () => {
103-
// Import vi locally to match the pattern used in the State 2 test
104101
const { vi } = await import('vitest');
105102

106-
// 1. Force the mongoose connection state to 0 (Disconnected)
107103
const readyStateSpy = vi
108104
.spyOn(mongoose.connection, 'readyState', 'get')
109105
.mockReturnValue(0 as unknown as typeof mongoose.connection.readyState);
110106

111107
expect(mongoose.connection.readyState).toBe(0);
112108

113-
// 2. Mock a database operation to simulate a connection failure
114-
// Mongoose throws specific errors when bufferCommands is false and state is 0
115109
const mockConnectionError = new Error('Database connection lost');
116110
mockConnectionError.name = 'ConnectionError';
117111

118112
const findOneSpy = vi.spyOn(User, 'findOne').mockRejectedValue(mockConnectionError);
119113

120-
// 3. Verify that attempting to query throws the expected ConnectionError
121114
await expect(User.findOne({ username: 'testuser' })).rejects.toThrow(
122115
'Database connection lost'
123116
);
124117
await expect(User.findOne({ username: 'testuser' })).rejects.toMatchObject({
125118
name: 'ConnectionError',
126119
});
127120

128-
// 4. Clean up mocks to prevent side effects in other tests
129121
readyStateSpy.mockRestore();
130122
findOneSpy.mockRestore();
131123
});
@@ -135,12 +127,10 @@ describe('User Model', () => {
135127
it('aborts/rolls back active transactions cleanly when connection is in state 3 (disconnecting)', async () => {
136128
const { vi } = await import('vitest');
137129

138-
// 1. Mock mongoose.connection.readyState to return 3 (disconnecting)
139130
const readyStateSpy = vi
140131
.spyOn(mongoose.connection, 'readyState', 'get')
141132
.mockReturnValue(3 as unknown as typeof mongoose.connection.readyState);
142133

143-
// 2. Mock a mongoose session with transaction support
144134
const mockSession = {
145135
startTransaction: vi.fn(),
146136
commitTransaction: vi.fn(),
@@ -150,7 +140,6 @@ describe('User Model', () => {
150140

151141
const startSessionSpy = vi.spyOn(mongoose, 'startSession').mockResolvedValue(mockSession);
152142

153-
// 3. Simulate a database transaction workflow that checks connection state
154143
const runTransactionWithCheck = async (session: mongoose.ClientSession) => {
155144
session.startTransaction();
156145
try {
@@ -171,15 +160,47 @@ describe('User Model', () => {
171160
const session = await mongoose.startSession();
172161
const result = await runTransactionWithCheck(session);
173162

174-
// 4. Assertions
175163
expect(result.status).toBe('aborted');
176164
expect(mockSession.abortTransaction).toHaveBeenCalledTimes(1);
177165
expect(mockSession.endSession).toHaveBeenCalledTimes(1);
178166
expect(mockSession.commitTransaction).not.toHaveBeenCalled();
179167

180-
// Cleanup
181168
readyStateSpy.mockRestore();
182169
startSessionSpy.mockRestore();
183170
});
184171
});
172+
173+
describe('Database Connection State 99 Handling', () => {
174+
it('triggers lazy initialization exactly once and uses the correct connection URI', async () => {
175+
const { vi } = await import('vitest');
176+
177+
// 1. Mock readyState to 99 (uninitialized — no connection ever attempted)
178+
const readyStateSpy = vi
179+
.spyOn(mongoose.connection, 'readyState', 'get')
180+
.mockReturnValue(99 as unknown as typeof mongoose.connection.readyState);
181+
182+
// 2. Stub mongoose.connect to capture what URI it was called with
183+
const connectSpy = vi.spyOn(mongoose, 'connect').mockResolvedValue(mongoose);
184+
185+
const MONGO_URI = 'mongodb://localhost:27017/commitpulse';
186+
187+
// 3. Simulate the lazy init fallback — connects exactly once with correct URI
188+
const lazyInit = async () => {
189+
if (mongoose.connection.readyState === 99) {
190+
await mongoose.connect(MONGO_URI);
191+
}
192+
};
193+
194+
await lazyInit();
195+
196+
// 4. Assertions
197+
expect(mongoose.connection.readyState).toBe(99);
198+
expect(connectSpy).toHaveBeenCalledTimes(1);
199+
expect(connectSpy).toHaveBeenCalledWith(MONGO_URI);
200+
201+
// 5. Cleanup
202+
readyStateSpy.mockRestore();
203+
connectSpy.mockRestore();
204+
});
205+
});
185206
});

0 commit comments

Comments
 (0)