【问题标题】:How to mock Knex using jest如何使用玩笑来模拟 Knex
【发布时间】:2021-08-09 20:01:12
【问题描述】:

我正在尝试使用 jest 来模拟 knex 以进行以下实现

 const knex = Knex({ client: "mysql"})

    const query = knex("table_name")
      .where({
        title: "xxx-yyy",
        lang: "eng"
      })
      .select()
      .orderBy('date', 'desc')
      .toSQL()
      .toNative()
      

下面我试过了,但是没用,出现错误“TypeError: knex is not a function”

jest.mock("knex", () => {
  return () => {
    return {
      knex: () => {
        where: () => {
          select: () => {
            orderBy: () => {
              toSQL: () => {
                toNative: jest.fn()
              }
            }
          }
        }
      }
    }
  }
})

非常感谢您对此的任何帮助。

【问题讨论】:

    标签: node.js jestjs mocking knex.js


    【解决方案1】:

    jest.mock() 将模拟具有自动模拟版本的模块,factoryoptions 是可选的。

    您可以使用mockFn.mockReturnThis() 来模拟方法链接调用。

    另外,如果你在模块作用域内初始化Knex,你需要在mock建立后require模块。

    例如

    index.js:

    import Knex from 'knex';
    
    const knex = Knex({ client: 'mysql' });
    
    export function main() {
      const query = knex('table_name')
        .where({
          title: 'xxx-yyy',
          lang: 'eng',
        })
        .select()
        .orderBy('date', 'desc')
        .toSQL()
        .toNative();
    }
    

    index.test.js:

    import Knex from 'knex';
    
    jest.mock('knex');
    
    describe('68717941', () => {
      test('should pass', () => {
        const querybuilder = {
          where: jest.fn().mockReturnThis(),
          select: jest.fn().mockReturnThis(),
          orderBy: jest.fn().mockReturnThis(),
          toSQL: jest.fn().mockReturnThis(),
          toNative: jest.fn(),
        };
        const mKnex = jest.fn().mockReturnValue(querybuilder);
        Knex.mockReturnValue(mKnex);
        const { main } = require('./');
        main();
        expect(Knex).toBeCalledWith({ client: 'mysql' });
        expect(mKnex).toBeCalledWith('table_name');
        expect(querybuilder.where).toBeCalledWith({ title: 'xxx-yyy', lang: 'eng' });
        expect(querybuilder.select).toBeCalledTimes(1);
        expect(querybuilder.orderBy).toBeCalledWith('date', 'desc');
        expect(querybuilder.toSQL).toBeCalledTimes(1);
        expect(querybuilder.toNative).toBeCalledTimes(1);
      });
    });
    

    测试结果:

     PASS  examples/68717941/index.test.js (8.844 s)
      68717941
        ✓ should pass (7464 ms)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |      100 |     100 |     100 |                   
     index.js |     100 |      100 |     100 |     100 |                   
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        9.439 s
    

    【讨论】:

      【解决方案2】:

      签出我写的一个小库knex-mock-client,它允许你编写一个单元测试,使用没有真正的数据库的数据库:]。

      这种方法的好处是,您不需要知道所有Knex's 内部(可能会随着时间的推移而改变),并且它允许您控制您的“数据库”应该为特定查询返回哪些数据。

      使用示例:

      // my-cool-controller.ts
      import { db } from '../common/db-setup';
      
      export async function addUser(user: User): Promise<{ id }> {
        const [insertId] = await db.insert(user).into('users');
      
        return { id: insertId };
      }
      
      // my-cool-controller.spec.ts
      import { expect } from '@jest/globals';
      import knex, { Knex } from 'knex';
      import { getTracker, MockClient } from 'knex-mock-client';
      import faker from 'faker';
      
      jest.mock('../common/db-setup', () => {
        return {
          db: knex({ client: MockClient })
        };
      });
      
      describe('my-cool-controller tests', () => {
        let tracker: Tracker;
      
        beforeAll(() => {
          tracker = getTracker();
        });
      
        afterEach(() => {
          tracker.reset();
        });
      
        it('should add new user', async () => {
          const insertId = faker.datatype.number();
          tracker.on.insert('users').response([insertId]);
          
          const newUser = { name: 'foo bar', email: 'test@test.com' };
          const data = await addUser(newUser);
      
          expect(data.id).toEqual(insertId);
      
          const insertHistory = tracker.history.insert;
      
          expect(insertHistory).toHaveLength(1);
          expect(insertHistory[0].method).toEqual('insert');
          expect(insertHistory[0].bindings).toEqual([newUser.name, newUser.email]);
        });
      });
      

      【讨论】:

        猜你喜欢
        • 2021-08-10
        • 2022-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-06
        • 2020-02-08
        • 2022-10-06
        • 2020-12-17
        相关资源
        最近更新 更多