简体   繁体   English

写入 Jest Mocked Prisma 数据库时遇到问题

[英]Trouble Writing to Jest Mocked Prisma Database

I have two databases that I need to interact with in my code.我有两个数据库需要在我的代码中进行交互。 I have a simple function that takes an object and writes it to my PostgreSQL database using Prisma.我有一个简单的函数,它接受一个对象并使用 Prisma 将它写入我的 PostgreSQL 数据库。 I've tested the function with Postman, and it works perfectly, but when I try to execute it using a Jest mock (using the singleton pattern found in the Prisma unit testing guide ), it returns undefined indicating that it didn't interact with the database and create the new record.我已经用 Postman 测试了该函数,它运行良好,但是当我尝试使用 Jest 模拟(使用Prisma 单元测试指南中的单例模式)执行它时,它返回 undefined 表示它没有与数据库并创建新记录。 Here's my code:这是我的代码:

/prisma/clinical-schema.prisma /prisma/clinical-schema.prisma

generator client {
  provider = "prisma-client-js"
  output   = "./generated/clinical"
}

datasource clinicalDatabase {
  provider = "postgresql"
  url      = "postgresql://postgres:postgres@localhost:5432/clinical-data?schema=public"
}

model pcc_webhook_update {
  id                  Int                       @id @default(autoincrement())
  event_type          String
  organization_id     Int
  facility_id         Int
  patient_id          Int
  resource_id         String?
  webhook_date        DateTime                  @default(now()) @clinicalDatabase.Timestamptz(6)
  status              pcc_webhook_update_status @default(pending)
  status_changed_date DateTime?                 @clinicalDatabase.Timestamptz(6)
  error_count         Int                       @default(0)

  @@unique([organization_id, facility_id, patient_id, resource_id, event_type, status])
}

enum pcc_webhook_update_status {
  pending
  processing
  processed
  error
}

/prisma/clinical-client.ts /prisma/clinical-client.ts

import { PrismaClient } from './generated/clinical';

const prismaClinical = new PrismaClient();

export default prismaClinical;

/testing/prisma-clinical-mock.ts /testing/prisma-clinical-mock.ts

import { PrismaClient } from '../prisma/generated/clinical';
import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended';
import prisma from '../prisma/clinical-client';

jest.mock('../prisma/clinical-client', () => ({
  __esModule: true,
  default: mockDeep<PrismaClient>()
}));

beforeEach(() => {
  mockReset(prismaClinicalMock);
});

export const prismaClinicalMock = prisma as unknown as DeepMockProxy<PrismaClient>;

Everything up to this point follows the conventions outlined by the Prisma unit testing docs.到目前为止,一切都遵循 Prisma 单元测试文档概述的约定。 The only modification I made was to make it database specific.我所做的唯一修改是使其特定于数据库。 Below is my function and tests.以下是我的功能和测试。 The request object in handle-pcc-webhooks.ts is a sample http request object, the body of which contains the webhook data I care about. handle-pcc-webhooks.ts中的请求对象是一个示例 http 请求对象,其主体包含我关心的 webhook 数据。

/functions/handle-pcc-webhooks/handler.ts /functions/handle-pcc-webhooks/handler.ts

import prismaClinical from '../../../prisma/clinical-client';
import { pcc_webhook_update } from '../../../prisma/generated/clinical';
import { requestObject } from './handler.types';

export const handlePccWebhook = async (request: requestObject) => {

  try {

    const webhook = JSON.parse(request.body);

    // if the webhook doesn't include a resource id array, set it to an array with an empty string to ensure processing and avoid violating
    // the multi-column unique constraint on the table
    const { resourceId: resourceIds = [''] } = webhook;

    let records = [];

    for (const resourceId of resourceIds) {

      // update an existing record if one exists in the pending state, otherwise create a new entry
      const record: pcc_webhook_update = await prismaClinical.pcc_webhook_update.upsert({
        where: {
          organization_id_facility_id_patient_id_resource_id_event_type_status: {
            organization_id: webhook.orgId,
            facility_id: webhook.facId,
            patient_id: webhook.patientId,
            resource_id: resourceId,
            event_type: webhook.eventType,
            status: 'pending'
          }
        },
        update: {
          webhook_date: new Date()
        },
        create: {
          event_type: webhook.eventType,
          organization_id: webhook.orgId,
          facility_id: webhook.facId,
          patient_id: webhook.patientId,
          resource_id: resourceId,
          status: 'pending' // not needed
        }
      });

      records.push(record);
    }

    return records;

  } catch (error) {

    console.error(error);
  }
};

/functions/handle-pcc-webhooks/handler.spec.ts /functions/handle-pcc-webhooks/handler.spec.ts

import fs from 'fs';
import path from 'path';
import MockDate from 'mockdate';
import { prismaClinicalMock } from '../../../testing/prisma-clinical-mock';
import { createAllergyAddRecord } from './__mocks__/allergy';
import { requestObject } from './handler.types';
import { handlePccWebhook } from './handler';

describe('allergy.add', () => {

  let requestObject: requestObject;
  let allergyAddRecord: any;

  beforeAll(() => {
    requestObject = getRequestObject('allergy.add');
  });

  beforeEach(() => {
    MockDate.set(new Date('1/1/2022'));
    allergyAddRecord = createAllergyAddRecord(new Date());
  });

  afterEach(() => {
    MockDate.reset();
  });

  test('should create an allergy.add database entry', async() => {

    prismaClinicalMock.pcc_webhook_update.create.mockResolvedValue(allergyAddRecord);

    // this is where I would expect handlePccWebhook to return the newly created database
    // record, but instead it returns undefined.  If I run the function outside of this
    // unit test, with the same input value, it functions perfectly
    await expect(handlePccWebhook(requestObject)).resolves.toEqual([allergyAddRecord]);
  });
});

// This just builds a request object with the current webhook being tested
function getRequestObject(webhookType: string) {

  // read the contents of request object file as a buffer, then convert it to JSON
  const rawRequestObject = fs.readFileSync(path.resolve(__dirname, '../../sample-data/handle-pcc-webhook-request.json'));
  const requestObject: requestObject = JSON.parse(rawRequestObject.toString());

  // read the contents of the webhook file as a buffer, then convert it to a string
  const rawWebhook = fs.readFileSync(path.resolve(__dirname, `../../sample-data/${webhookType}.json`));
  const webhookString = rawWebhook.toString();

  // set the body of the request object to the contents of the target webhook
  requestObject.body = webhookString;

  return requestObject;
}

Finally, here is the result of running the unit test:最后,这是运行单元测试的结果:

在此处输入图像描述

什么给了一个尝试,赶上模拟?

So after banging my had against the wall for a few hours, I figured out the issue.所以在把我的头发撞到墙上几个小时后,我发现了这个问题。 In my handler.spec.ts file, I had the following line:在我的handler.spec.ts文件中,我有以下行:

prismaClinicalMock.pcc_webhook_update.create.mockResolvedValue(allergyAddRecord);

what that does is mock the value returned for any create functions run using Prisma.这样做是模拟使用 Prisma 运行的任何create函数返回的值。 The issue is that my function is using an upsert function, which I wasn't explicitly mocking, thus returning undefined.问题是我的函数正在使用一个upsert函数,我没有明确地模拟它,因此返回未定义。 I changed the above line to我将上面的行更改为

prismaClinicalMock.pcc_webhook_update.upsert.mockResolvedValue(allergyAddRecord);

and it started working.它开始工作了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM