Skip to content

Commit 2d54289

Browse files
committed
chore: continue with testing
1 parent c18c204 commit 2d54289

File tree

18 files changed

+1467
-2
lines changed

18 files changed

+1467
-2
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# 13-unit-test-mock-other-modules
2+
3+
Demonstrates how to mock internal or third-party modules
4+
5+
## Run
6+
7+
To run the example launch:
8+
9+
```
10+
node --test --experimental-test-module-mocks
11+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export class DbClient {
2+
// biome-ignore lint/suspicious/useAwait: just for demonstration
3+
async query(_sql, _params) {
4+
// In real life, this would talk to a database
5+
throw new Error('Not implemented')
6+
}
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "13-unit-test-mock-other-modules",
3+
"version": "1.0.0",
4+
"description": "Demonstrates how to mock internal or third-party modules",
5+
"type": "module",
6+
"scripts": {},
7+
"engines": {
8+
"node": ">=22"
9+
},
10+
"engineStrict": true,
11+
"keywords": [],
12+
"author": "Luciano Mammino and Mario Casciaro",
13+
"license": "MIT",
14+
"dependencies": {}
15+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { DbClient } from './dbClient.js'
2+
3+
const db = new DbClient()
4+
5+
export async function canPayWithVouchers(userId, amount) {
6+
const vouchers = await db.query(
7+
`SELECT * FROM vouchers
8+
WHERE user_id = ? AND
9+
balance > 0 AND
10+
expiresAt > NOW()`,
11+
[userId]
12+
)
13+
14+
const availableBalance = vouchers.reduce((acc, v) => acc + v.balance, 0)
15+
16+
return availableBalance >= amount
17+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import assert from 'node:assert/strict'
2+
import { after, beforeEach, mock, suite, test } from 'node:test'
3+
import { setImmediate } from 'node:timers/promises'
4+
5+
const sampleRecords = [
6+
{
7+
id: 1,
8+
userId: 'user1',
9+
balance: 10,
10+
expiresAt: new Date(Date.now() + 1000),
11+
},
12+
{
13+
id: 2,
14+
userId: 'user1',
15+
balance: 5,
16+
expiresAt: new Date(Date.now() + 1000),
17+
},
18+
{
19+
id: 3,
20+
userId: 'user1',
21+
balance: 3,
22+
expiresAt: new Date(Date.now() + 1000),
23+
},
24+
]
25+
26+
const queryMock = mock.fn(async (_sql, _params) => {
27+
await setImmediate()
28+
return sampleRecords
29+
})
30+
31+
mock.module('./dbClient.js', {
32+
cache: false,
33+
namedExports: {
34+
// biome-ignore lint/style/useNamingConvention: <explanation>
35+
DbClient: class DbMock {
36+
query = queryMock
37+
},
38+
},
39+
})
40+
41+
const { canPayWithVouchers } = await import('./payments.js')
42+
43+
suite('canPayWithVouchers', { concurrency: false, timeout: 500 }, () => {
44+
beforeEach(() => {
45+
queryMock.mock.resetCalls()
46+
})
47+
48+
after(() => {
49+
queryMock.mock.restore()
50+
})
51+
52+
test('Returns true if balance is enough', async () => {
53+
const result = await canPayWithVouchers('user1', 18)
54+
55+
assert.equal(result, true)
56+
assert.equal(queryMock.mock.callCount(), 1)
57+
})
58+
59+
test('Returns false if balance is not enough', async () => {
60+
const result = await canPayWithVouchers('user1', 19)
61+
62+
assert.equal(result, false)
63+
assert.equal(queryMock.mock.callCount(), 1)
64+
})
65+
})
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# 13-unit-test-mock-other-modules
2+
3+
Demonstrates how to mock internal or third-party modules
4+
5+
## Run
6+
7+
To run the example launch:
8+
9+
```
10+
node --test --experimental-test-module-mocks
11+
```
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export class DbClient {
2+
// biome-ignore lint/suspicious/useAwait: just for demonstration
3+
async query(_sql, _params) {
4+
// In real life, this would talk to a database
5+
throw new Error('Not implemented')
6+
}
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "13-unit-test-mock-other-modules",
3+
"version": "1.0.0",
4+
"description": "Demonstrates how to mock internal or third-party modules",
5+
"type": "module",
6+
"scripts": {},
7+
"engines": {
8+
"node": ">=22"
9+
},
10+
"engineStrict": true,
11+
"keywords": [],
12+
"author": "Luciano Mammino and Mario Casciaro",
13+
"license": "MIT",
14+
"dependencies": {}
15+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export async function canPayWithVouchers(db, userId, amount) {
2+
const vouchers = await db.query(
3+
`SELECT * FROM vouchers
4+
WHERE user_id = ? AND
5+
balance > 0 AND
6+
expiresAt > NOW()`,
7+
[userId]
8+
)
9+
10+
const availableBalance = vouchers.reduce((acc, v) => acc + v.balance, 0)
11+
12+
return availableBalance >= amount
13+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import assert from 'node:assert/strict'
2+
import { suite, test } from 'node:test'
3+
import { setImmediate } from 'node:timers/promises'
4+
import { canPayWithVouchers } from './payments.js'
5+
6+
const sampleRecords = [
7+
{
8+
id: 1,
9+
userId: 'user1',
10+
balance: 10,
11+
expiresAt: new Date(Date.now() + 1000),
12+
},
13+
{
14+
id: 2,
15+
userId: 'user1',
16+
balance: 5,
17+
expiresAt: new Date(Date.now() + 1000),
18+
},
19+
{
20+
id: 3,
21+
userId: 'user1',
22+
balance: 3,
23+
expiresAt: new Date(Date.now() + 1000),
24+
},
25+
]
26+
27+
suite('canPayWithVouchers', { concurrency: true, timeout: 500 }, () => {
28+
test('Returns true if balance is enough', async t => {
29+
const dbMock = {
30+
query: t.mock.fn(async (_sql, _params) => {
31+
await setImmediate()
32+
return sampleRecords
33+
}),
34+
}
35+
36+
const result = await canPayWithVouchers(dbMock, 'user1', 18)
37+
38+
assert.equal(result, true)
39+
assert.equal(dbMock.query.mock.callCount(), 1)
40+
})
41+
42+
test('Returns false if balance is not enough', async t => {
43+
const dbMock = {
44+
query: t.mock.fn(async (_sql, _params) => {
45+
await setImmediate()
46+
return sampleRecords
47+
}),
48+
}
49+
50+
const result = await canPayWithVouchers(dbMock, 'user1', 19)
51+
52+
assert.equal(result, false)
53+
assert.equal(dbMock.query.mock.callCount(), 1)
54+
})
55+
})

0 commit comments

Comments
 (0)