Jest 每次都测试不同类型的相同承诺响应
Jest testing the same promise response in different types each time
如何正确测试可以不同类型的相同承诺响应?
例如,当从 Cloud Firestore 数据库中获取项目集合时,响应是一种数组类型,但是有一种方法可以与响应进行交互,就像它是一种对象类型一样。这是代码:
// ...
await Database.collection('products').select('published').get().then(snapshot => {
snapshot.forEach(doc => { // <---- HERE snapshot IS AN ARRAY
if (doc.data().published) {
// ...
}
})
console.log(snapshot.docs.length) // <---- HERE snapshot IS AN OBJECT. HOW ?
console.log(snapshot.size) // IT'S THE SAME AS snapshot.docs.length
})
// ...
我试图通过在每次调用后返回一个不同的值来测试它,但它现在正在工作,我收到一个错误: TypeError: Cannot read property 'length' of undefined
:
jest.doMock('@google-cloud/firestore', () => class {
constructor () {
this.collection = jest.fn().mockImplementation((collectionName) => {
if (collectionName === 'products') {
return {
select: () => ({
get: jest.fn().mockResolvedValueOnce([ // <--- AN ARRAY
{
data: () => {
return {
published: false
}
}
}
]).mockResolvedValueOnce({ // <---- AN OBJECT
docs: () => []
})
}),
limit: () => ({ get: async () => ({ empty: true }) })
}
}
})
}
})
这是怎么回事?在所有这些嘲笑中我应该使用什么?:
mockImplementation
mockImplementationOnce
mockResolvedValue
mockResolvedValueOnce
mockReturnValue
mockReturnValueOnce
您不需要使用 class 来创建测试替身。这让事情变得复杂。只需使用 JS 普通对象数据类型 - Array
来制作 firestore 的查询快照。使用Object
制作查询文档快照。
您可以将自定义属性添加到 JS 数组,例如 snapshot.docs
和 snapshot.size
。
例如
index.ts
:
import { Firestore } from '@google-cloud/firestore';
export async function main() {
const Database = new Firestore();
await Database.collection('products')
.select('published')
.get()
.then((snapshot) => {
snapshot.forEach((doc) => {
if (doc.data().published) {
console.log(doc.data());
}
});
console.log(snapshot.docs.length);
console.log(snapshot.size);
});
}
index.test.ts
:
describe('71058297', () => {
beforeEach(() => {
jest.resetModules();
});
test('should pass', async () => {
const mDocument1 = { data: jest.fn(() => ({ published: true, name: 'steam deck' })) };
const mQuerySnapshot: any = [mDocument1];
mQuerySnapshot.docs = mQuerySnapshot;
mQuerySnapshot.size = mQuerySnapshot.docs.length;
const mFirestore = {
collection: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
get: jest.fn().mockResolvedValueOnce(mQuerySnapshot),
};
const MockFireStore = jest.fn(() => mFirestore);
jest.doMock('@google-cloud/firestore', () => ({ Firestore: MockFireStore }));
const { main } = require('./');
await main();
expect(MockFireStore).toBeCalledTimes(1);
expect(mFirestore.collection).toBeCalledWith('products');
expect(mFirestore.select).toBeCalledWith('published');
expect(mFirestore.get).toBeCalledTimes(1);
expect(mDocument1.data).toBeCalledTimes(2);
});
});
测试结果:
PASS Whosebug/71058297/index.test.ts
71058297
✓ should pass (24 ms)
console.log
{ published: true, name: 'steam deck' }
at Whosebug/71058297/index.ts:33:17
at Array.forEach (<anonymous>)
console.log
1
at Whosebug/71058297/index.ts:36:13
console.log
1
at Whosebug/71058297/index.ts:37:13
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.595 s, estimated 2 s
如何正确测试可以不同类型的相同承诺响应?
例如,当从 Cloud Firestore 数据库中获取项目集合时,响应是一种数组类型,但是有一种方法可以与响应进行交互,就像它是一种对象类型一样。这是代码:
// ...
await Database.collection('products').select('published').get().then(snapshot => {
snapshot.forEach(doc => { // <---- HERE snapshot IS AN ARRAY
if (doc.data().published) {
// ...
}
})
console.log(snapshot.docs.length) // <---- HERE snapshot IS AN OBJECT. HOW ?
console.log(snapshot.size) // IT'S THE SAME AS snapshot.docs.length
})
// ...
我试图通过在每次调用后返回一个不同的值来测试它,但它现在正在工作,我收到一个错误: TypeError: Cannot read property 'length' of undefined
:
jest.doMock('@google-cloud/firestore', () => class {
constructor () {
this.collection = jest.fn().mockImplementation((collectionName) => {
if (collectionName === 'products') {
return {
select: () => ({
get: jest.fn().mockResolvedValueOnce([ // <--- AN ARRAY
{
data: () => {
return {
published: false
}
}
}
]).mockResolvedValueOnce({ // <---- AN OBJECT
docs: () => []
})
}),
limit: () => ({ get: async () => ({ empty: true }) })
}
}
})
}
})
这是怎么回事?在所有这些嘲笑中我应该使用什么?:
mockImplementation
mockImplementationOnce
mockResolvedValue
mockResolvedValueOnce
mockReturnValue
mockReturnValueOnce
您不需要使用 class 来创建测试替身。这让事情变得复杂。只需使用 JS 普通对象数据类型 - Array
来制作 firestore 的查询快照。使用Object
制作查询文档快照。
您可以将自定义属性添加到 JS 数组,例如 snapshot.docs
和 snapshot.size
。
例如
index.ts
:
import { Firestore } from '@google-cloud/firestore';
export async function main() {
const Database = new Firestore();
await Database.collection('products')
.select('published')
.get()
.then((snapshot) => {
snapshot.forEach((doc) => {
if (doc.data().published) {
console.log(doc.data());
}
});
console.log(snapshot.docs.length);
console.log(snapshot.size);
});
}
index.test.ts
:
describe('71058297', () => {
beforeEach(() => {
jest.resetModules();
});
test('should pass', async () => {
const mDocument1 = { data: jest.fn(() => ({ published: true, name: 'steam deck' })) };
const mQuerySnapshot: any = [mDocument1];
mQuerySnapshot.docs = mQuerySnapshot;
mQuerySnapshot.size = mQuerySnapshot.docs.length;
const mFirestore = {
collection: jest.fn().mockReturnThis(),
select: jest.fn().mockReturnThis(),
get: jest.fn().mockResolvedValueOnce(mQuerySnapshot),
};
const MockFireStore = jest.fn(() => mFirestore);
jest.doMock('@google-cloud/firestore', () => ({ Firestore: MockFireStore }));
const { main } = require('./');
await main();
expect(MockFireStore).toBeCalledTimes(1);
expect(mFirestore.collection).toBeCalledWith('products');
expect(mFirestore.select).toBeCalledWith('published');
expect(mFirestore.get).toBeCalledTimes(1);
expect(mDocument1.data).toBeCalledTimes(2);
});
});
测试结果:
PASS Whosebug/71058297/index.test.ts
71058297
✓ should pass (24 ms)
console.log
{ published: true, name: 'steam deck' }
at Whosebug/71058297/index.ts:33:17
at Array.forEach (<anonymous>)
console.log
1
at Whosebug/71058297/index.ts:36:13
console.log
1
at Whosebug/71058297/index.ts:37:13
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.595 s, estimated 2 s