cjp666
cjp666

Reputation: 69

Writing JavaScript tests that test other functions are called, without actually calling them

I have been tasked with writing unit tests for some AngularJS code that was written by another team, who didn't write any tests

They have written the following function but I cannot figure out how to test it

function showCallAlerts(callRecord, isInEditMode, callBack) {
    var callAlerts = populateCallAlertOnEditCall(callRecord.callAlert);
    var callModalInstance = openAlertModalInstance('Call', callAlerts, callBack);
    if (callModalInstance !== undefined && callModalInstance !== null) {
    callModalInstance.result.then(function() {
        // Show equipment alerts based on company details
        showEquipmentAlertsBasedOnCompanyDetails(callRecord, isInEditMode, callBack);
    });
    } else {
    // Show equipment alerts based on company details
    showEquipmentAlertsBasedOnCompanyDetails(callRecord, isInEditMode, callBack);
    }
}

I need to test that each of the functions are called, not worrying about what they do as I'll test them separate, just that they are called.

When populateCallAlertOnEditCall is called it needs to either return an empty array or an array with some items in it

When openAlertModalInstance is called it needs to either return undefined or something that passes through to showEquipmentAlertsBasedOnCompanyDetails

showEquipmentAlertsBasedOnCompanyDetails should actually be called, I'll test that method separate, just that it was called

I have manged to write code to test simple functions but nothing like this one so any help will be much appreciated, I spent most of this afternoon trying to figure it out

Upvotes: 0

Views: 122

Answers (3)

brianyang
brianyang

Reputation: 1140

the test that something has been called, you can use a Spy

your assertion would look like:

spyOn(obj, 'populateCallAlertOnEditCall')
expect(obj.method).toHaveBeenCalled()

UPDATED:

populateCallAlertOnEditCall = {}
spyOn(obj, 'populateCallAlertOnEditCall.result')
expect(obj.method).toHaveBeenCalled()

Upvotes: 1

Pedro Vaz
Pedro Vaz

Reputation: 820

You can use jasmine to mock the function calls that you are not interested in testing. For example, you can tell jasmine to return an empty array every time 'populateCallAlertOnEditCall' is called. I will write an example that might give you an insight:

describe('My Test Spec', function() {
   var myController;

   ...

   beforeEach( inject(($controller) => {
        myController = $controller("myControllerName");
   }));

  it('Testing showCallAlerts when populateCallAlertOnEditCall returns an empty array', inject(function($controller) {
        //setup
        //this will replace every call to populateCallAlertOnEditCall with
        //the function inside callFake
        spyOn(myController, 'populateCallAlertOnEditCall ').and.callFake(function() {
              return []; //returning an empty array.
        });

        //action
        myController.showCallAlerts(...);

        //assert
        //Do your checking here.
  }));

  it('Testing showCallAlerts when populateCallAlertOnEditCall returns a non-empty array', inject(function($controller) {
        //setup
        //this will replace every call to populateCallAlertOnEditCall with
        //the function inside callFake
        spyOn(myController, 'populateCallAlertOnEditCall ').and.callFake(function() {
              return [1,2,3,4]; //returning a non-empty array.
        });

        //action
        myController.showCallAlerts(...);

        //assert
        //Do your checking here.
  }));

 });

Upvotes: 3

Fábio Junqueira
Fábio Junqueira

Reputation: 2781

The kind of behaviour you want is called mocking

In Jasmine, mocking is done with Spy Objects, you can read more about those here

Basically, you can use mocks to test if functions were called with the expected parameters.

var xhr = mock( XMLHttpRequest );

xhr.send();

expect( xhr.send ).toHaveBeenCalled();

Upvotes: 1

Related Questions