我有一个类方法,可以多次触发 @google-cloud/firestore
。我想多次模拟对同一个 .get()
方法的调用。
多次使用 mockResolvedValueOnce
并返回不同的值,第二个值将被忽略。
jest.doMock('@google-cloud/firestore', () => class {
collection () {
return {
get: jest.fn().mockResolvedValue({
docs: []
}),
doc: () => {
return {
set: jest.fn(),
get: jest.fn().mockResolvedValueOnce({})
}
},
limit: () => {
return {
get: jest.fn().mockResolvedValue({ empty: true })
}
},
onSnapshot: jest.fn(),
select: () => {
return {
get: jest.fn() // <------------ MULTIPLE CALLS CHAINED BELOW
.mockResolvedValueOnce({
size: 1
}).mockResolvedValueOnce({
size: 2
})
}
}
}
}
})
当我 console.log(snapshot.size)
时,两次调用都会返回相同的值“1”两次。
if (isEmptyModels || isStatsEmptyModels) {
// ...
console.log('📊 [STATS][MODELS] - Fulfilling the counters')
await Database.collection('models').select('id').get().then(snapshot => {
console.log(snapshot.size) // <--------- 1st call
this.fields.models.count = snapshot.size
this.fields.models.linked = snapshot.size
})
// ...
}
if (isEmptyProducts1P || isStatsEmptyProducts1P) {
// ...
console.log('📊 [STATS][PRODUCTS1P] - Fulfilling the counters')
await Database.collection('products1P').select('isMaintained').get().then(snapshot => {
console.log(snapshot.size) // <--------- 2nd call
snapshot.forEach(doc => {
if (doc.data().isMaintained) {
// ...
}
})
// ...
})
// ...
}
这是为什么,这里做错了什么?
错误消息是:
console.log
📊 [STATS][MODELS] - Fulfilling the counters
at Statistics.fulfillProductsCount (app/services/statistics/index.js:95:15)
console.log
1
at app/services/statistics/index.js:97:17
console.log
📊 [STATS][PRODUCTS1P] - Fulfilling the counters
at Statistics.fulfillProductsCount (app/services/statistics/index.js:106:15)
console.log
1
at app/services/statistics/index.js:108:17
TypeError: snapshot.forEach is not a function
117 | await Database.collection('products1P').select('isMaintained').get().then(snapshot => {
118 | console.log(snapshot.size)
> 119 | snapshot.forEach(doc => {
| ^
120 | if (doc.data().isMaintained) {
121 | this.fields.products1P.maintained += 1
122 | } else {
at app/services/statistics/index.js:119:18
最佳答案
发生这种情况是因为每次调用Database.collection()
时,它都会创建一个新对象,并且作为一个新对象,这是第一次调用它的属性。它对于集合内的其他函数也有效。
我的意思是 Database.collection 是一个返回一个对象的函数,该对象包含其他函数,这些函数返回包含模拟属性的对象。通过这种方式模拟,您将永远无法使用模拟...ValueOnce。但是,我看到有两种方法可以“绕过”这个问题:
1 - 简短但矛盾的方式
您可以使用.mockReturnThis()
来避免进入深层模拟对象/函数,但在处理具有多次相同方法名称的“胖”类时可能会很快发生冲突。在模拟可链接方法时也很有帮助(例如:使用 .find().filter().sort()... 进行 ORM 查询。
jest.doMock('@google-cloud/firestore', () => class {
collection = jest.fn().mockReturnThis();
select = jest.fn().mockReturnThis();
get = jest.fn().mockResolvedValueOnce({ size: 1 }).mockResolvedValueOnce({ size: 2 });
})
2 - 漫长但有效的方法
模拟整个集合方法一次,而不是仅模拟 collection().select().get()
。
Database.collection.prototype.mockReturnValueOnce({
select: () => {
get: () => ({ size: 1 })
}
}).mockReturnValueOnce({
select: () => {
get: () => ({ size: 2 })
}
})
--> 您将需要访问模拟的类并模拟原型(prototype)的方法“集合”(collection = jest.fn())。
关于node.js - 为什么多次调用 jest mockResolvedValueOnce 返回相同的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71049272/