如何在 TypeORM 中存根嵌套存储库?

How to stub nested Repository in TypeORM?

我没能成功找到如何存根 typeorm 嵌套存储库。有人可以帮我为以下代码构建一个 sinon 存根吗?我在另一个 Whosebug 问题中找到的测试文件中有一些代码,但它不起作用。 我希望存根的具体代码行是:

const project = await getManager().getRepository(Project).find({ where: queryParams });

这是源代码:

project.controller.ts

//getConnection and UpdateResult not used in this function btw
import {
  EntityManager,
  getConnection,
  getManager,
  UpdateResult,
} from "typeorm";
import { Project } from "./project.entity";
import { validate } from "class-validator";
import logger from "../../utils/logger";
export const findOneProject = async (queryParams: {}): Promise<
  Project
> => {
  try {
    const project = await getManager().getRepository(Project).find({
      where: queryParams,
    });
    if (project.length > 1) {
      throw new Error("Found more than one project");
    }
    return project[0];
  } catch (e) {
    throw new Error(`Unable to find project: ${e.message}`);
  }
};

project.test.ts

import sinon from "sinon";
import {  findOneProject } from "./project.controller";
import { Project } from "./project.entity";
import { EntityManager, Repository } from "typeorm";

const mockProject = {
  ID: "insert-id-here",
  name: "name",
};

describe("Testing findOneProject", () => {
  it("Should return the same project", () => {
    const sandbox = sinon.createSandbox();
    // I think that i can get the repository to be stubbed but idk how to stub the find()
    sandbox.stub(EntityManager.prototype, "get").returns({
      getRepository: sandbox
        .stub()
        .returns(sinon.createStubInstance(Repository)),
    });
    const project = await findOneProject(ID: "insert-id-here");
    expect(project).toBe(mockProject);
  });
});

提前致谢!

编辑:我在测试文件中添加了更多内容以使其更清楚我正在尝试做什么

您可以使用 Link Seams with CommonJS, so we will be using proxyquire 构建我们的接缝。

例如

project.controller.ts:

import { getManager } from 'typeorm';
import { Project } from './project.entity';

export const findOneProject = async (queryParams: {}): Promise<Project> => {
  try {
    const project = await getManager()
      .getRepository(Project)
      .find({
        where: queryParams,
      });
    if (project.length > 1) {
      throw new Error('Found more than one project');
    }
    return project[0];
  } catch (e) {
    throw new Error(`Unable to find project: ${e.message}`);
  }
};

project.entity.ts:

export class Project {
  // whatever
}

project.controller.test.ts:

import sinon from 'sinon';
import chai, { expect } from 'chai';
import proxyquire from 'proxyquire';
import { Project } from './project.entity';
import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised);

const mockProject = {
  ID: 'insert-id-here',
  name: 'name',
};

describe('Testing findOneProject', () => {
  let sandbox: sinon.SinonSandbox;
  before(() => {
    sandbox = sinon.createSandbox();
  });
  it('Should return the same project', async () => {
    const typeormStub = {
      getManager: sandbox.stub().returnsThis(),
      getRepository: sandbox.stub().returnsThis(),
      find: sandbox.stub().resolves([mockProject]),
    };
    const { findOneProject } = proxyquire('./project.controller', {
      typeorm: typeormStub,
    });

    const project = await findOneProject({ id: 1 });
    sandbox.assert.calledOnce(typeormStub.getManager);
    sandbox.assert.calledWithExactly(typeormStub.getRepository, Project);
    sandbox.assert.calledWithExactly(typeormStub.find, { where: { id: 1 } });
    expect(project).to.be.eq(mockProject);
  });

  it('should throw error if found more than one project', async () => {
    const typeormStub = {
      getManager: sandbox.stub().returnsThis(),
      getRepository: sandbox.stub().returnsThis(),
      find: sandbox.stub().resolves([{ name: 'a' }, { name: 'b' }]),
    };
    const { findOneProject } = proxyquire('./project.controller', {
      typeorm: typeormStub,
    });

    await expect(findOneProject({ id: 1 })).to.be.rejectedWith('Found more than one project');
    sandbox.assert.calledOnce(typeormStub.getManager);
    sandbox.assert.calledWithExactly(typeormStub.getRepository, Project);
    sandbox.assert.calledWithExactly(typeormStub.find, { where: { id: 1 } });
  });

  it('should throw error if find project error', async () => {
    const typeormStub = {
      getManager: sandbox.stub().returnsThis(),
      getRepository: sandbox.stub().returnsThis(),
      find: sandbox.stub().rejects(new Error('timeout')),
    };
    const { findOneProject } = proxyquire('./project.controller', {
      typeorm: typeormStub,
    });

    await expect(findOneProject({ id: 1 })).to.be.rejectedWith('Unable to find project: timeout');
    sandbox.assert.calledOnce(typeormStub.getManager);
    sandbox.assert.calledWithExactly(typeormStub.getRepository, Project);
    sandbox.assert.calledWithExactly(typeormStub.find, { where: { id: 1 } });
  });
});

单元测试结果:

  Testing findOneProject
    ✓ Should return the same project (2395ms)
    ✓ should throw error if found more than one project
    ✓ should throw error if find project error


  3 passing (2s)

-----------------------|---------|----------|---------|---------|-------------------
File                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------------------|---------|----------|---------|---------|-------------------
All files              |     100 |      100 |     100 |     100 |                   
 project.controller.ts |     100 |      100 |     100 |     100 |                   
 project.entity.ts     |     100 |      100 |     100 |     100 |                   
-----------------------|---------|----------|---------|---------|-------------------