我有以下型号:

    const Invoice = sequelize.define("invoice", {
        number: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: { msg: "Invoice number already exists" },
            validate: { ...notEmptyMsg("Invoice number") },
        },
        dateIssued: {
            type: DataTypes.DATE,
            allowNull: false,
            validate: isDateMsg("dateIssued"),
        },
        dueDate: {
            type: DataTypes.DATE,
            allowNull: false,
            validate: {
                ...isDateMsg("dueDate"),
                isAfterDateIssued(value) {
                    if (this.dateIssued && value < this.dateIssued) {
                        throw new Error("Due date cannot be before the date issued");
                    }
                },
            },
        },
        sender: {
            type: DataTypes.TEXT,
            allowNull: false,
            validate: notEmptyMsg("Sender"),
        },
        recipient: {
            type: DataTypes.TEXT,
            allowNull: false,
            validate: notEmptyMsg("Recipient"),
        },
        items: {
            type: DataTypes.JSON,
            allowNull: false,
            validate: { isArrayOfItems: validateItemsArray },
        },
        status: {
            type: DataTypes.ENUM("Draft", "Issued", "Paid", "Part Paid", "Cancelled", "Disputed", "On Hold"),
            allowNull: false,
            validate: {
                isIn: {
                    args: [["Draft", "Issued", "Paid", "Part Paid", "Cancelled", "Disputed", "On Hold"]],
                    msg: "Invalid status",
                },
            },
        },
        footnotes: {
            type: DataTypes.TEXT,
            allowNull: true,
            validate: {
                isString(value) {
                    if (typeof value !== "string") {
                        throw new Error("Footnotes must be a string");
                    }
                },
            },
        },
        organizationId: {
            type: DataTypes.INTEGER,
            allowNull: false,
            references: { model: "organizations", key: "id" },
        },
        // Virtual field calculating total
        total: {
            type: DataTypes.VIRTUAL,
            get() {
                return parseFloat(
                    this.items
                        .reduce((acc, item) => acc + item.quantity * item.unitPrice * (1 + item.taxRate), 0)
                        .toFixed(2)
                );
            },
        },
        // Virtual field calculating subtotal
        subtotal: {
            type: DataTypes.VIRTUAL,
            get() {
                return this.items.reduce((acc, item) => acc + item.quantity * item.unitPrice, 0);
            },
        },
    });

在更新字段时,我遇到了一个关于虚拟字段的奇怪问题.

以下测试通过:

    test("Update an invoice", async () => {
        const invoiceData = createInvoiceData();
        const invoice = await Invoice.create(invoiceData);

        await invoice.update({ recipient: "Lorem" });

        expect(invoice.recipient).toBe("Lorem");
    });

但这一次抛出了一个错误:

    test("Update an invoice", async () => {
        const invoiceData = createInvoiceData();
        const invoice = await Invoice.create(invoiceData);

        await Invoice.update({ recipient: "Lorem" }, { where: { id: invoice.id } });
        const updatedInvoice = await Invoice.findByPk(invoice.id);

        expect(updatedInvoice.recipient).toBe("Lorem");
    });

这是错误:

  ● Invoice Model › Update an invoice

    TypeError: Cannot read properties of undefined (reading 'reduce')

      129 |                 return parseFloat(
      130 |                     this.items
    > 131 |                         .reduce((acc, item) => acc + item.quantity * item.unitPrice * (1 + item.taxRate), 0)
          |                          ^
      132 |                         .toFixed(2)
      133 |                 );
      134 |             },

      at model.reduce (src/models/invoice.js:131:8)
      at model.get (node_modules/sequelize/src/model.js:3651:41)
      at model.get (node_modules/sequelize/src/model.js:3685:33)
      at Function.update (node_modules/sequelize/src/model.js:3247:44)
      at Object.update (tests/invoice.model.test.js:72:17)

显然,在这种情况下,当试图计算虚拟字段"总数"时,项是"未定义的".

我不明白为什么第二种写作方法失败了.我在更新数据库,不是吗?

More strangely even是这样一个事实,在测试中失败的同一个方法在生产代码中似乎工作得很好.这就是我在express 路由上做的事情:

exports.updateInvoice = async (req, res, next) => {
    try {
        const [updateCount] = await Invoice.update(
            { ...req.body },
            {
                where: { id: req.params.id },
            }
        );

而且它工作起来没有任何问题.

UPDATE

有趣的细节我注意到了.如果我在测试用例中更新的是items字段,则测试通过...

    test("Update an invoice (Method #1)", async () => {
        const invoiceData = createInvoiceData();
        const invoice = await Invoice.create(invoiceData);
        await Invoice.update({ items: [] }, { where: { id: invoice.id } });
        const updatedInvoice = await Invoice.findByPk(invoice.id);
        expect(updatedInvoice.items.length).toBe(0);
    });

推荐答案

我似乎找到了解决问题的方法.如果我将模型声明为"类",而不是使用sequelize.define,则测试通过.

    class Invoice extends Model {
        // Virtual field for calculating total
        get total() {
            return parseFloat(
                this.items
                    .reduce((acc, item) => acc + item.quantity * item.unitPrice * (1 + item.taxRate), 0)
                    .toFixed(2)
            );
        }

        // Virtual field for calculating subtotal
        get subtotal() {
            return this.items.reduce((acc, item) => acc + item.quantity * item.unitPrice, 0);
        }
    }

我不知道为什么另一种方式行不通,但这至少是一种解决方案.

Node.js相关问答推荐

express返回意外的URL

Stripe webhook无法访问Express请求原始正文

Sequelize-测试使用虚拟场更新模型

如何呈现ejs.renderFile中包含的子模板?

下一个API路由如何处理多个并发请求?

Inno Setup如何在现有文本文件中追加新内容

Axios TypeError:将循环 struct 转换为 JSON

遇到 - TypeError:try 使用 Express(Node.js) 从 JSON 文件访问数据时无法读取未定义的属性(读取帖子)

如何使用 Remix 仅在客户端呈现组件?

如何在mongodb中获取对象数组内部的数据

为什么要加密 CSRF 令牌?

看起来这段代码try GET 请求发送的值变为空白

Sharp JS 依赖关系 destruct 了 Elastic Beanstalk 上的 Express Server

为什么在调用数据库调用时我的参数没有定义?

如何在 cypress 测试中进行计算

使用 $in 查询时,如何获取 mongoDB 中每个唯一 ID 的 n 个文档?

NodeJS为exec设置环境变量

所有的javascript回调都是异步的吗?如果不是,我怎么知道哪些是?

对不同对象中的函数使用相同的键时,V8 中的函数调用缓慢

`return function *(){...}` 是什么意思?