You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Node.js开发API时,Bookshelf.js模型调用ModelName.forge(...).destroy出现TypeError错误求助

Fixing TypeError: ModelName.forge(...).destroy is not a function in Bookshelf.js

Let's break down this issue step by step and get it fixed. The error tells us the destroy method isn't available on your model instance, which usually stems from either a misconfigured model, incorrect test stubbing, or a problem with your Bookshelf setup.

1. First, Fix Your Model Definition

Looking at your model code, there are a couple of red flags that could break the inheritance of Bookshelf's built-in methods like destroy:

  • Missing import for OtherModel: Your model references OtherModel in the otherModel relation, but you haven't imported it. This will throw an error during model initialization, preventing it from inheriting Bookshelf's core methods. Add the import:

    const bookshelf = require('./bookshelf')
    const Intake = require('./intake')
    const OtherModel = require('./otherModel') // Replace with the correct path to your model
    const ModelName = bookshelf.Model.extend(
      {
        tableName: 'modelName',
        hasTimestamps: true,
        uuid: true,
        otherModel: function() {
          return this.hasOne(OtherModel)
        }
      },
      { dependents: ['otherModel'] }
    )
    module.exports = ModelName
    
  • Check the uuid: true setting: This requires the bookshelf-uuid plugin. If you haven't registered it with Bookshelf, your model might fail to initialize properly. Add this to your bookshelf.js setup:

    const bookshelf = require('bookshelf')(knexInstance)
    bookshelf.plugin('bookshelf-uuid') // Ensure this line exists
    
  • Verify model inheritance: Quick sanity check—add a log before exporting your model to confirm destroy exists on the prototype:

    console.log(ModelName.prototype.destroy) // Should log a function, not undefined
    module.exports = ModelName
    

2. Fix Your Test Stubbing (The Big Issue Here)

Your test code isn't stubbing the actual code path being executed. You created a local deleteModelName stub, but it has no connection to the ModelNameService.deleteModelName method or the Bookshelf model calls inside it. That's why the real code is running and throwing the error.

Here's the corrected test stubbing approach:

describe('#deleteModelName', () => {
  it('should call deleteModelName and resolve correctly', async () => {
    // Create a mock model instance with a stubbed destroy method
    const mockModel = {
      destroy: sandbox.stub().resolves(CreatedModelName)
    }
    // Stub ModelName.forge to return our mock instance
    sandbox.stub(ModelName, 'forge').returns(mockModel)

    // Call the service method with a test ID
    const result = await ModelNameService.deleteModelName('test-id-123')

    // Verify the calls happened as expected
    expect(ModelName.forge).to.have.been.calledWith({ id: 'test-id-123' })
    expect(mockModel.destroy).to.have.been.calledOnce()
    expect(result).to.equal(CreatedModelName) // Your destroy resolves this value, so result won't be undefined
  })
})

This stubs the exact ModelName.forge() and destroy() calls your service uses, so you're testing the service's logic without hitting the database.

3. Double-Check Your Bookshelf/Knex Setup

Ensure your root bookshelf.js file correctly initializes Knex with valid database credentials. A broken Knex connection can prevent Bookshelf models from loading their core methods:

const knex = require('knex')({
  client: 'pg', // Or your database type (mysql, sqlite3, etc.)
  connection: {
    host: 'your-db-host',
    user: 'your-db-user',
    password: 'your-db-password',
    database: 'your-db-name'
  }
})

const bookshelf = require('bookshelf')(knex)
module.exports = bookshelf

Final Quick Checks

  • Restart your test environment to ensure all code changes take effect.
  • Test the deleteModelName function in isolation (outside tests) with a valid ID to confirm the model works as expected:
    const ModelNameService = require('./modelNameService')
    ModelNameService.deleteModelName('existing-id')
      .then(() => console.log('Delete successful'))
      .catch(err => console.error('Delete failed:', err))
    

内容的提问来源于stack exchange,提问作者Julissa DC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:38:09