gpt4 book ai didi

mysql - 用 Jest 模拟 mysql 连接

转载 作者:行者123 更新时间:2023-12-04 11:55:19 34 4
gpt4 key购买 nike

尝试测试如下所示的代码:

const mysql = require('mysql2/promise');

async myFunction () {

const db = await mysql.createConnection(options);

const results = await db.execute('SELECT `something` from `table`;');

await db.end();

// more code ...

}
我需要以一种允许我使用它返回的任何内容来模拟对 execute 的调用的方式来模拟 mysql 连接。功能。
我试过 mock 整个 mysql2/promise模块,但当然这不起作用,因为被 mock 的 createConnection没有返回任何可以调用 execute 的东西功能。
我还尝试只模拟我需要的这 3 个函数,而不是模拟整个模块,例如:
jest.mock('mysql2/promise', () => ({
createConnection: jest.fn(() => ({
execute: jest.fn(),
end: jest.fn(),
})),
}));
但这也不起作用。
任何建议都非常感谢。

最佳答案

我会以不同的方式处理这个问题。当你觉得你需要模拟整个第三方库进行测试时,你的应用程序中出现了一些问题。
作为一般的最佳实践,您应该始终包装第三方库。退房 this discussion对于初学者。
基本上的想法是定义您自己的接口(interface)到所需的功能,然后使用第三方库实现这些接口(interface)。在您的其余代码中,您将只针对接口(interface)工作,而不是针对第三方实现。
这有几个优点

  • 您可以自己定义接口(interface)。它通常比整个第三方库小得多,因为您很少使用该第三方库的所有功能,并且您可以决定什么是具体用例的最佳接口(interface)定义,而不必完全遵循某些图书馆作者决定你。
  • 如果有一天您决定不想再使用 MySQL 而是转而使用 Mongo,那么您只需编写 DB 接口(interface)的 Mongo 实现即可。
  • 就您而言,最重要的是:您可以轻松创建数据库接口(interface)的模拟实现,而无需开始模拟整个第三方 API。

  • 那么这怎么可能呢?
    首先,定义一个接口(interface),因为它在您的代码中最有用。也许,您的数据库接口(interface)可能如下所示:
    interface Database<T> {
    create(object: T): Promise<void>;
    get(id: string): Promise<T>;
    getAll(): Promise<T[]>;
    update(id: string, object: T): Promise<void>;
    delete(id: string): Promise<void>;
    }
    现在,您可以针对此开发您的整个代码库 Database界面。当您需要从“表”中检索数据时,您可以使用 Database,而不是在整个代码中编写 MySQL 查询。执行。
    我就举个例子 ResultRetriever这里很原始,但达到了目的:
    class ResultRetriever {

    constructor(private database: Database<Something>) {}

    getResults(): Promise<Something[]> {
    return this.database.getAll();
    }

    }
    如您所见,您的代码不需要关心哪个 DB 实现提供了数据。另外,我们 inverted dependencies这里: ResultReteriver注入(inject) 它的 Database实例。它不知 Prop 体是哪个 Database它得到的实现。它不需要。它所关心的只是它是一个有效的。
    您现在可以轻松实现 MySQL Database类(class):
    class MySqlDatabase<T> implements Database<T> {

    create(object: T): Promise<void> {...}

    get(id: string): Promise<T> {...}

    getAll(): Promise<T[]> {
    const db = await mysql.createConnection(options);
    const results = await db.execute('SELECT `something` from `table`;');
    await db.end();
    return results;
    }

    update(id: string, object: T): Promise<void> {...}

    delete(id: string): Promise<void> {...}

    }
    现在我们已经从您的主要代码库中完全抽象出特定于 MySQL 的实现。说到测试,可以写一个简单的 MockDatabase :
    export class MockDatabase<T> implements Database<T> {

    private objects: T[] = [];

    async create(object: T): Promise<void> {
    this.objects.push(object);
    }

    async get(id: string): Promise<T> {
    return this.objects.find(o => o.id === id);
    }

    async getAll(): Promise<T[]> {
    return this.objects;
    }

    update(id: string, object: T): Promise<void> {...}

    delete(id: string): Promise<void> {...}

    }
    说到测试,您现在可以测试您的 ResultRetrieve使用您的 MockDatabase而不是依赖 MySQL 库,因此完全模拟它:
    describe('ResultRetriever', () => {

    let retriever: ResultRetriever;
    let db: Database;

    beforeEach(() => {
    db = new MockDatabase();
    retriever = new ResultRetriever(db);
    });

    ...

    });

    如果我有点超出了问题的范围,我很抱歉,但我觉得仅仅回答如何模拟 MySQL 库并不能解决底层的架构问题。
    如果您不使用/不想使用 TypeScript,则可以将相同的逻辑应用于 JavaScript。

    关于mysql - 用 Jest 模拟 mysql 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63596277/

    34 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com