conn.commitAsync не является ошибкой функции при запуске в качестве транзакции

#node.js #mocking #knex.js #node-oracledb

#node.js #издевательство #knex.js #узел-oracledb

Вопрос:

Когда я запускаю приведенный ниже код, я продолжаю получать эту ошибку:

 TypeError: conn.commitAsync is not a function
    at Oracle_Transaction.commit (/home/foo/node_modules/knex/lib/dialects/oracledb/transaction.js:14:18)
    at Function.transactor.commit (/home/foo/node_modules/knex/lib/transaction.js:277:40)
    at /home/foo/node_modules/knex/lib/transaction.js:191:35
 

Похоже, у меня нет проблем, если я запускаю без транзакции, поэтому я предполагаю, что это неявные коммиты, которые захлебываются. Кстати, это нормально работает регулярно, только когда я пытаюсь издеваться над ним, это не удается.

Я что-то упустил? Это соединение, которое не издевается, как мне его издеваться, если это проблема?

 import * as knex from 'knex';

export const pool: any = knex({
    acquireConnectionTimeout: 60000,
    client: 'oracledb',
    connection: {
        connectString: 'zoo',
        password: 'foo',
        user: 'bar',
    },
    debug: true,
    pool: {
        acquireTimeoutMillis: 60000, 10),
        idleTimeoutMillis: 60000,
        max: 10,
        min: 10,
    },
});

    await pool.transaction((trx: any) => {
        return Promise.all([
            row = this.insertOne(trx, id, data),
            this.insertTwo(trx, id, data),
            userData.flag ? this.insertThree(trx, id, data) : {},
            this.insertFour(trx, id, data),
            moreToDo(data),
        ]);
    })
    .catch((err: any) => {
        logger.error(err);
    });
 

каждая из функций вставки выглядит примерно так

     public insertOne(trx: any,  id: number, data: any) {
    return pool('FOOBAR')
            .transacting(trx)
            .withSchema('FOO')
            .insert([
                {
                    FOO: 'BAR',
                    ID: id,
                    CREATE_DT: pool.raw('sysdate'),
                    LAST_MOD_DT: pool.raw('sysdate'),
                },
            ]);
}
 

Это издевается так

 import * as mockKnex from 'mock-knex';
mockKnex.mock(pool);
const tracker = mockKnex.getTracker();
tracker.install();
    tracker.on('query', (query, step) => {
        [
            function firstQuery() {
                    {
                        ID: 1234,
                    },
                ]);
            },
            function secondQuery() {
                query.response([
                    {
                        ID: 1234,
                    },
                ]);
            },
            function thirdQuery() {
                query.response([]);
            },
            function fourthQuery() {
                query.response([]);
            },
            function fifthQuery() {
                query.response([]);
            },
        ][step - 1]();
    });
    const results = await sut.inserts(subject);
    expect(results).toEqual(foo);
 

Я пробовал использовать вложенный .тогда и операторы, такие как документация knex, делают это с явной фиксацией или откатом, та же проблема.

Комментарии:

1. Даже если он работает нормально, когда не издевается, убедитесь, что вы понимаете, почему использование Promise.all в одном соединении (если это то, что делает Knex) не рекомендуется, см. Документ node-oracledb .

2. Относится ли это также к пулам? т.Е. Будет ли он выполняться только при одном соединении, даже при использовании пула? Я предполагаю, что библиотека-макет (mock-knex) неправильно высмеивает соединения в пуле при использовании транзакций. Есть ли лучшая библиотека?

3. Соединение — это соединение, поэтому, да, оно применяется к пулам.

Ответ №1:

Для тех, кто столкнулся с такой же проблемой, я смог заставить это работать, добавив jest.spyOn в функцию отката и фиксации в классе Transaction в oracledb

 // tslint:disable: no-var-requires
// tslint:disable: no-require-imports
// tslint:disable-next-line: variable-name
const Transaction  = require('../../node_modules/knex/lib/dialects/oracledb/transaction.js');

const rollbackMock = jest.spyOn(Transaction.prototype, 'rollback');
const commitkMock = jest.spyOn(Transaction.prototype, 'commit');
 

в beforeEach()

 jest.resetAllMocks();
rollbackMock.mockImplementation(() => null);
commitkMock.mockImplementation(() => null);