1

How do I go about unit testing a method that calls the DialogController? I want to test that this.controller.ok() was called.

ReprocessLotDialog.js

@inject(DialogController)
export class ReprocessLotDialog {
    constructor(dialogController) {
        this.controller = dialogController;
    }


    commitReprocessingLot() {    
        this.controller.ok({
            reprocessLot: this.model
        });
    }    

    commitIncompleteBags(){
       ... do stuff ....
       this.commitReprocessingLot();
    }
}

myDialog.spec.js I've tried this but can't get it to work

describe("The ReprocessLotDialog module", ()=> {
    let sut;

    beforeEach(()=> {
        var container = new Container().makeGlobal();
        container.registerInstance(DialogController,controller => new DialogController());
        sut = container.get(ReprocessLotDialog);
    });


     it("commitReprocessingLot() should call controller.ok", (done)=> {    
        spyOn(sut, "controller.ok");

        sut.commitIncompleteBags();
        expect(sut.controller.ok).toHaveBeenCalled();
        done();
    });
});

The test fails with TypeError: 'undefined' is not a function (evaluating 'this.controller.ok({ reprocessLot: this.model })')

As far as I understand it I'm passing the DialogController through DI into the container and container.get(ReprocessLotDialog) injects the DialogController into the ctor.

I've also tried container.registerInstance(DialogController,{"dialogController":DialogController}); but that doesn't work either.

Many thanks

Jeremy Holt
  • 987
  • 1
  • 9
  • 14

2 Answers2

1

Your unit tests shouldn't be utilizing the DI container. You simply new up an instance of ReprocessLotDialog and pass in a mock of DialogController that you created. If you're using Jasmine, it would look something like this:

describe("The ReprocessLotDialog module", ()=> {
 it("commitReprocessingLot() should call controller.ok", ()=> {    
    let dialogController = {
          ok: (arg) = { }
        };

    spyOn(dialogController, "ok");

    let sut = new ReprocessLotDialog(dialogController);

    sut.commitIncompleteBags();
    expect(dialogController.ok).toHaveBeenCalled();
  });
});

You might also want to consider if testing if you shouldn't just be testing if commitReprocessingLot has been called instead of checking that it calls the method that's the only thing it does (at least in your example).

describe("The ReprocessLotDialog module", ()=> {
 it("commitReprocessingLot() should call controller.ok", ()=> {    
    let dialogController = {
          ok: (arg) = { }
        };

    let sut = new ReprocessLotDialog(dialogController);

    spyOn(sut, "commitReprocessingLot");

    sut.commitIncompleteBags();
    expect(su.commitReprocessingLot).toHaveBeenCalled();
  });
});
Ashley Grant
  • 10,879
  • 24
  • 36
  • 1
    Both your and Patrick's answers were so helpful! I thought it was obligatory to use the DI when testing. Is there any documentation on the best practices for testing in aurelia? – Jeremy Holt Apr 30 '16 at 01:34
0

You can definitely stub out the controller or you can just spy on the instance method like this -

describe("The ReprocessLotDialog module", ()=> {
    let container;
    let sut;
    let controller;

    beforeEach(()=> {
        container = new Container().makeGlobal();
        controller = container.get(DialogController);
        sut = container.get(ReprocessLotDialog);
    });


     it("commitReprocessingLot() should call controller.ok", (done)=> {    
        spyOn(controller, 'ok');
        sut.commitIncompleteBags();
        expect(controller.ok).toHaveBeenCalled();
        done();
    });
});

Basically you should be able to create an instance in your container of the controller that will get passed in and you can spyOn the method directly on the instance.

PW Kad
  • 14,953
  • 7
  • 49
  • 82