首页 > 解决方案 > Upsert 实现委托更新但不委托添加

问题描述

我不习惯 javascript 或 node.js。这是我第一次尝试认真对待它,因为我的雇主要求我这样做。顺便说一句,这是我的代码:

//meta-dao.js
class MetaDAO {
    async getAll() {
        return await Meta.find().exec()
    }
    async getByCatalogId(catalogId) {
        return await Meta.find().where(catalogId).in('catalogs').exec()
    }
    async getById(id) {
        return await Meta.findOne({ id }).exec()
    }
    async add(meta) {
        return await (new Meta(meta)).save()
    }
    async update(meta) {
        return await Meta.update({ id: meta.id }, meta).exec()
    }
    async upsert(meta) {
        var exists = await this.getById(meta.id)
        console.log(exists)
        if(!exists){
            return await this.add(meta)
        }
        else {
            return await this.update(meta)
        }
    }
}
//meta-dao.test.js
it('Should insert when upsert a meta with new id', async () => {
    metaDAO.getById = jest.fn((id) => {
        return Promise.resolve(meta)
    })
    metaDAO.getById.bind(metaDAO)

    metaDAO.upsert(meta)

    expect(metaDAO.add).toBeCalledTimes(1)
    expect(metaDAO.add).toBeCalledWith(meta)
    expect(metaDAO.getById).toBeCalledTimes(1)
    expect(metaDAO.getById).toBeCalledWith(meta.id)
    expect(metaDAO.update).not.toBeCalled()
})
it('Should update when upsert a meta with known id', async () => {
    metaDAO.getById = jest.fn((id) => {
        return Promise.resolve(null)
    })
    metaDAO.getById.bind(metaDAO)

    metaDAO.upsert(meta)

    expect(metaDAO.update).toBeCalledTimes(1)
    expect(metaDAO.update).toBeCalledWith(meta)
    expect(metaDAO.getById).toBeCalledTimes(1)
    expect(metaDAO.getById).toBeCalledWith(meta.id)
    expect(metaDAO.add).not.toBeCalled()
})

第二个测试用例的所有断言都通过了。但是expect(metaDAO.add).toBeCalledTimes(1)从第一个测试用例开始就失败了。console.log 打印“null”,我已经尝试过使用:

它似乎没有任何区别。行为是

我究竟做错了什么?我错过了什么吗?

标签: javascriptnode.jsmongoosejestjs

解决方案


我的嘲笑是不正确的。而不是jest.fn()and fn.bind(object),我应该使用jest.spyOnand spy.mockRestore()

以下代码已更正并有效!

//meta-dao.test.js
beforeAll(() => {
    metaDAO = new MetaDAO()
})
it('Should insert when upsert a meta with new id', async () => {
    const addSpy = jest.spyOn(metaDAO,"add").mockImplementation(()=>{})
    const updateSpy = jest.spyOn(metaDAO,"update").mockImplementation(()=>{})
    const getIdSpy = jest.spyOn(metaDAO,"getById").mockImplementation((id) => {
        return Promise.resolve(null)
    })
    metaDAO.getById.bind(metaDAO)

    await metaDAO.upsert(meta)

    expect(addSpy).toBeCalledTimes(1)
    expect(addSpy).toBeCalledWith(meta)
    expect(getIdSpy).toBeCalledTimes(1)
    expect(getIdSpy).toBeCalledWith(meta.id)
    expect(updateSpy).not.toBeCalled()

    addSpy.mockRestore()
    updateSpy.mockRestore()
    getIdSpy.mockRestore()
})
it('Should update when upsert a meta with known id', async () => {
    const addSpy = jest.spyOn(metaDAO,"add").mockImplementation(()=>{})
    const updateSpy = jest.spyOn(metaDAO,"update").mockImplementation(()=>{})
    const getIdSpy = jest.spyOn(metaDAO,"getById").mockImplementation((id) => {
        return Promise.resolve(meta)
    })
    metaDAO.getById.bind(metaDAO)

    await metaDAO.upsert(meta)

    expect(updateSpy).toBeCalledTimes(1)
    expect(updateSpy).toBeCalledWith(meta)
    expect(getIdSpy).toBeCalledTimes(1)
    expect(getIdSpy).toBeCalledWith(meta.id)
    expect(addSpy).not.toBeCalled()

    addSpy.mockRestore()
    updateSpy.mockRestore()
    getIdSpy.mockRestore()
})

另一方面,源代码已经可以了。


推荐阅读