Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular Jasmine test function call inside then

Here is my controller function I want to test.

  saveItem = (): void => {
    this.updateItem();
    this.loadingDialogService.showIndicator("Saving Item");        
this._editItemService.updateItem(this.item).then((updatedItem: Item) => {
            this.loadingDialogService.cancelDialog();
            this.goToMainView();
        }).catch(() => {
            this.loadingDialogService.showErrorDialog("Failed to Save Item");
            //this._log.error("Error CallingItemService");
        });
    }

Here is my test:

it("should call method saveItem", () => {
            spyOn(controller, 'updateItem');
            spyOn(loadingDialogService, 'showIndicator');
            spyOn(editItemService, 'updateItem').and.callFake(() => {
                let result: Item
                deferred.resolve(result);  
                return deferred.promise;              
            });
            spyOn(loadingDialogService, 'cancelDialog');
            spyOn(controller, 'goToMainView');
            controller.saveItem();
            expect(controller.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.showIndicator).toHaveBeenCalled();
            expect(_editItemService.updateItem).toHaveBeenCalled();
            expect(loadingDialogService.cancelDialog).toHaveBeenCalled();
            expect(controller.goToMainView).toHaveBeenCalled();
        });

The test fails at the last two expects, throws error saying that

Expected spy cancelDialog to have been called.

Expected spy goToMainView to have been called.

I guess the test doesn't execute the functions inside then function. Could some one point out where the mistake is?

like image 873
Aj1 Avatar asked Feb 10 '16 17:02

Aj1


People also ask

How do you test a function call in Jasmine?

With Jasmine async testing, we have to call the async code in the beforeEach() function that runs before each it() function block within a describe() function block. We also have to let Jasmine know when the async function has completed by calling the special done() callback function Jasmine provides.

How do you call a function in a test case?

Following are the steps to call a test case. Step 1 − Go to the Test Step section, where you want to call a test case. Step 2 − Go to individual step where the user will call the function. Step 3 − In the Settings tab of the Test step, click the Test Case icon as shown in the following screenshot.

What is done () in Jasmine?

If the function passed to Jasmine takes an argument (traditionally called done ), Jasmine will pass a function to be invoked when asynchronous work has been completed.

How can you wrap a function in async testing?

fakeAsync and tick Like async we wrap the test spec function in a function called fakeAsync . We call tick() when there are pending asynchronous activities we want to complete. Like the async function the fakeAsync function executes the code inside its body in a special fake async test zone.


1 Answers

You have a promise to resolve, so you need to run a digest cycle after your function call but before your tests.

it("should call method saveItem", () => {
        spyOn(controller, 'updateItem');
        spyOn(loadingDialogService, 'showIndicator');
        spyOn(editItemService, 'updateItem').and.callFake(() => {
            let result: Item
            deferred.resolve(result);  
            return deferred.promise;              
        });
        spyOn(loadingDialogService, 'cancelDialog');
        spyOn(controller, 'goToMainView');
        controller.saveItem();
        $scope.$digest();
        expect(controller.updateItem).toHaveBeenCalled();
        expect(loadingDialogService.showIndicator).toHaveBeenCalled();
        expect(_editItemService.updateItem).toHaveBeenCalled();
        expect(loadingDialogService.cancelDialog).toHaveBeenCalled();
        expect(controller.goToMainView).toHaveBeenCalled();
    });

Having said that, your test is going to lead you to problems later because it has 5 assertions (expect()s) in it. When one fails you will have to waste time figuring out which one it is. Stick to One Assertion Per Test (OAPT.) This should be 5 tests with one assertion each. That way, when something fails you know right what it is.

like image 150
MBielski Avatar answered Oct 11 '22 22:10

MBielski