簡體   English   中英

開玩笑模擬 Knex 交易

[英]Jest mock Knex transaction

我有以下 lambda 處理程序進行單元測試。 它使用一個庫@org/aws-connection ,它有一個function mysql.getIamConnection ,它只返回一個knex連接。

編輯:我已將mysql.getIamConnection function 添加到帖子底部

編輯:如果可能的話,我想只用 Jest 進行測試。 那是除非它變得復雜

index.js

const {mysql} = require('@org/aws-connection');

exports.handler = async (event) => {
  const connection = await mysql.getIamConnection()

  let response = {
    statusCode: 200,
    body: {
      message: 'Successful'
    }
  }

  try {
    for(const currentMessage of event.Records){
      let records = JSON.parse(currentMessage.body);
      
      await connection.transaction(async (trx) => {
        await trx
            .table('my_table')
            .insert(records)
            .then(() =>
                console.log(`Records inserted into table ${table}`))
            .catch((err) => {
                console.log(err)
                throw err
            })
      })
    }
  } catch (e) {
    console.error('There was an error while processing', { errorMessage: e})

    response = {
      statusCode: 400,
      body: e
    }
  } finally {
    connection.destroy()
  }
  return response
}

我已經編寫了一些單元測試,並且能夠模擬connection.transaction function 但我遇到了 trx.select.insert.then.catch 函數的問題。 H

這是我的測試文件 index.test.js

import { handler } from '../src';
const mocks = require('./mocks');

jest.mock('@org/aws-connection', () => ({
    mysql: {
        getIamConnection: jest.fn(() => ({
            transaction: jest.fn(() => ({
                table: jest.fn().mockReturnThis(),
                insert: jest.fn().mockReturnThis()
            })),
            table: jest.fn().mockReturnThis(),
            insert: jest.fn().mockReturnThis(),
            destroy: jest.fn().mockReturnThis()
        }))
    }
}))

describe('handler', () => {
    test('test handler', async () =>{
      const response = await handler(mocks.eventSqs)
      expect(response.statusCode).toEqual(200)
    });
});

此測試部分有效,但根本不涵蓋trx部分。 這些線是暴露的

await trx
        .table('my_table')
        .insert(records)
        .then(() =>
            console.log(`Records inserted into table ${table}`))
        .catch((err) => {
            console.log(err)
            throw err
        })

如何設置我的模擬@org/aws-connection以便它也涵蓋 trx 功能?

編輯:mysql.getIamConnection

async function getIamConnection (secretId, dbname) {
    const secret = await getSecret(secretId)

    const token = await getToken(secret)

    let knex
    console.log(`Initialzing a connection to ${secret.proxyendpoint}:${secret.port}/${dbname} as ${secret.username}`)
    knex = require('knex')(
        {
            client: 'mysql2',
            connection: {
                host: secret.proxyendpoint,
                user: secret.username,
                database: dbname,
                port: secret.port,
                ssl: 'Amazon RDS',
                authPlugins: {
                    mysql_clear_password: () => () => Buffer.from(token + '\0')
                },
                connectionLimit: 1
            }
        }
    )

    return knex
}

解決方案

@qaismakani 的回答對我有用。 我寫的略有不同,但回調是關鍵。 對於任何對此感興趣的人是我的最終解決方案

const mockTrx = {
    table: jest.fn().mockReturnThis(),
    insert: jest.fn().mockResolvedValue()
}

jest.mock('@org/aws-connection', () => ({
    mysql: {
        getIamConnection: jest.fn(() => ({
            transaction: jest.fn((callback) => callback(mockTrx)),
            destroy: jest.fn().mockReturnThis()
        }))
    }
}))

我編寫knex-mock-client而不是 mocking knex 實現,它允許您使用簡單的 API 模擬真實數據庫。

更改您的模擬實現

import { handler } from "../src";
import { getTracker } from "knex-mock-client";
const mocks = require("./mocks");

jest.mock("@org/aws-connection", () => {
  const knex = require("knex");
  const { MockClient } = require("knex-mock-client");
  return {
    mysql: {
      getIamConnection: () => knex({ client: MockClient }),
    },
  };
});

describe("handler", () => {
  test("test handler", async () => {
    const tracker = getTracker();
    tracker.on.insert("my_table").responseOnce([23]); // setup's a mock response when inserting into my_table

    const response = await handler(mocks.eventSqs);
    expect(response.statusCode).toEqual(200);
  });
});

好吧,讓我們看看。 更新你的模擬看起來像這樣可能會奏效:


const {mysql} = require('@org/aws-connection');
jest.mock('@org/aws-connectionm, () => ({
    mySql: {
        getIamConnection: jest.fn()
    }
}));


const mockTrx = {
  table: jest.fn().mockReturnThis(),
  insert: jest.fn().mockResolveValue() // resolve any data here
};
mysql.getIamConnection.mockReturnValue({
    transaction: jest.fn((callback) => callback(mockTrx)),
});

編輯:解釋

您需要以一種使用虛擬 trx 調用回調的方式模擬事務。 現在要正確獲取虛擬 trx,您需要確保 dummy trx object 中的所有函數都返回對它的引用或 promise,以便您可以適當地鏈接它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM