-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdb-connection.test.ts
More file actions
114 lines (95 loc) · 3.87 KB
/
db-connection.test.ts
File metadata and controls
114 lines (95 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { Prisma } from '@prisma/client';
import logger from '../../utils/logger';
import { createMockPrismaClient } from '../prisma-mock';
import { mockDeep } from 'jest-mock-extended';
// Replace jest-fail-fast which can't be found
const fail = (message: string): never => {
throw new Error(message);
};
describe('Database Connection', () => {
let prisma: ReturnType<typeof createMockPrismaClient>;
beforeEach(() => {
prisma = createMockPrismaClient();
});
it('should connect to the database successfully', async () => {
// Mock the query response
prisma.$queryRaw.mockResolvedValue([{ result: 1 }]);
const result = await prisma.$queryRaw`SELECT 1 as result`;
expect(result).toBeDefined();
expect(result).toEqual([{ result: 1 }]);
});
it('should handle connection pool correctly', async () => {
// Mock multiple parallel queries
for (let i = 0; i < 5; i++) {
prisma.$queryRaw.mockResolvedValueOnce([{ value: Math.random() }]);
}
const promises = Array(5)
.fill(0)
.map(() => prisma.$queryRaw`SELECT random() as value`);
const results = await Promise.all(promises);
expect(results.length).toBe(5);
expect(results.every(r => Array.isArray(r) && r.length === 1)).toBe(true);
});
it('should handle transaction rollback correctly', async () => {
// Mock successful transaction
const mockTx = mockDeep<Prisma.TransactionClient>();
// First mock a successful query
mockTx.$executeRaw.mockResolvedValueOnce(1);
// Then mock a failing query
const duplicateKeyError = new Error('Duplicate key value');
mockTx.$executeRaw.mockRejectedValueOnce(duplicateKeyError);
// Fix the callback type to match Prisma's $transaction overloads
// Define transaction related types
type TransactionCallback<T> = (tx: Prisma.TransactionClient) => Promise<T>;
type TransactionQueries<T> = Array<Promise<T>>;
prisma.$transaction.mockImplementation(
<T>(
callbackOrQueries: TransactionCallback<T> | TransactionQueries<T>,
): Promise<T | Array<T>> => {
if (typeof callbackOrQueries === 'function') {
return callbackOrQueries(mockTx).catch(error => {
throw error instanceof Error ? error : new Error(String(error));
});
}
// Handle the array of queries case
return Promise.all(callbackOrQueries);
},
);
try {
await prisma.$transaction(async tx => {
// This should succeed
await tx.$executeRaw`CREATE TEMPORARY TABLE test_table (id SERIAL PRIMARY KEY)`;
// This will deliberately fail
await tx.$executeRaw`INSERT INTO test_table (id) VALUES (1), (1)`;
});
fail('Transaction should have failed');
} catch (error: unknown) {
expect(error).toBeDefined();
expect(error).toEqual(duplicateKeyError);
}
});
it('should handle connection errors gracefully', async () => {
// Instead of creating a real bad client, we'll mock a connection error
// Fix constructor arguments to match expected signature
const mockError = new Prisma.PrismaClientInitializationError(
"Can't reach database server",
'4.5.0',
);
// No need to set clientVersion property as it's now provided in the constructor
prisma.$queryRaw.mockRejectedValueOnce(mockError);
try {
await prisma.$queryRaw`SELECT 1`;
fail('Query should have failed with database connection error');
} catch (error: unknown) {
// Add proper error handling logic to satisfy SonarQube
expect(error).toBeDefined();
expect(error).toBe(mockError);
if (error instanceof Prisma.PrismaClientInitializationError) {
expect(error.message).toContain("Can't reach database server");
logger.error(`Database connection error: ${error.message}`);
} else {
fail('Error should be a PrismaClientInitializationError');
}
}
});
});