Search code examples
node.jsunit-testingmocha.jssinontypeorm

How can i test a TypeORM repository method with local dependency


I'm new to Node and I'm trying to test a TypeORM custom Repository with Mocha and Sinon, without hitting the database.

My Repository has a method that takes 2 parameters and returns a Promise. It uses a local query builder and I would like to spy it (the queryBuilder) to know how many times its methods are called. This is my custom Repository:


@EntityRepository(Pratica)
export class PraticaRepository extends Repository<Pratica> {

    list(targa?: string, tipoVeicolo?: string): Promise<Pratica[]> {
        fileLogger.log('info','inizio -  targa: %s; tipoVeicolo %s.', targa, tipoVeicolo);

        let queryBuilder: SelectQueryBuilder<Pratica> = this.createQueryBuilder("p")
        .leftJoinAndSelect("p.stato", "stato")
        .leftJoinAndSelect("p.microstato", "microstato");
        let filtered: boolean = false;

        if(targa && targa !== ""){
            fileLogger.debug("Applico filtro targa");
            filtered = true;
            queryBuilder.where("p.targa = :targa", {targa: targa});
        }

        if(tipoVeicolo && tipoVeicolo !== ""){
            if(!filtered){
                fileLogger.debug("Applico filtro tipoVeicolo");
                filtered = true;
                queryBuilder.where("p.tipoVeicolo = :tipoVeicolo", {tipoVeicolo: tipoVeicolo});
            }else{
                fileLogger.debug("Applico filtro tipoVeicolo come parametro aggiuntivo");
                queryBuilder.andWhere("p.tipoVeicolo = :tipoVeicolo", {tipoVeicolo: tipoVeicolo});
            }
        }

        fileLogger.log('debug', "Sql generato: %s", queryBuilder.getSql);
        fileLogger.info("fine");

        return queryBuilder.getMany();

    }

I've tryed something like the following:

describe('PraticaRepository#list', () => {

    it.only('should call getMany once', async () => {

        let result = new Promise((resolve,reject) => {
            resolve(new Array(new Pratica(), new Pratica()))
        });

        let getMany = sinon.stub().returns(result);

        typeorm.createQueryBuilder = sinon.stub().returns({
            select: sinon.stub(),
            from: sinon.stub(),
            leftJoinAndSelect: sinon.stub(),
            where: sinon.stub(),
            orderBy: sinon.stub(),
            getMany: getMany
          })

        let cut = new PraticaRepository();

        const appo = cut.list('','');

        sinon.assert.calledOnce(getMany);
    });
})

But obviously i get the following error:

1) PraticaRepository#list
       should call getMany once:
     TypeError: Cannot read property 'createQueryBuilder' of undefined
      at PraticaRepository.Repository.createQueryBuilder (src\repository\Repository.ts:50:29)
      at PraticaRepository.list (src\repositories\PraticaRepository.ts:12:62)

because the query builder I'm stubbing is not the one instantiated inside the Repository method. My questions:

  • Is it possible to spy a method like this?
  • Is this method "Unit Testable"? Or should I test it only against some functional/integration test.

Thank you in advance.


Solution

  • Thanks to the suggestions of @oligofren this is my final solution:

    let sandbox;
    let createQueryBuilderStub;
    let mock;
    let fakeQueryBuilder = new SelectQueryBuilder<Pratica>(null);
    
    beforeEach(() => {
        sandbox = sinon.createSandbox();
    
        mock = sandbox.mock(fakeQueryBuilder);
    
        createQueryBuilderStub = sandbox.stub(Repository.prototype, 
    'createQueryBuilder').withArgs("p").returns(fakeQueryBuilder);
    });
    
    afterEach(() => {
        sandbox.restore();
    });
    
    describe('PraticaRepository#list', () => {
    
        it('should get the result with no filters', async () => {
    
            mock.expects('leftJoinAndSelect').twice().returns(fakeQueryBuilder);
            mock.expects('where').never();
            mock.expects('andWhere').never();
            mock.expects('getSql').once();
            mock.expects('getMany').once();
    
            let cut = new PraticaRepository();
    
            const appo = cut.list();
    
            sinon.assert.calledOnce(createQueryBuilderStub);
            mock.verify();
    
        });
    })