unit-testingember.jsember-testing

How to unit test an ember controller


I have a single action defined in an ember controller that calls 2 separate functions that are part of the controller. I'd like to mock out those functions in a unit test in order to confirm if the action method called the correct function.

My controller looks like this:

export default Ember.Controller.extend({
    functionA() {
        return;
    },
    functionB() {
        return;
    },
    actions: {
        actionMethod(param) {
            if(param) {
                return this.functionA();
            }
            else {
                return this.functionB();
            }
         }
    }
});

In practice, the controller works, however in the unit test, functionA and functionB are both undefined. I tried to log this to the console, but can't find where functionA and functionB are, so I'm unable to properly mock them. I expected them to be in the top level of the object next to actions, but instead I only found _actions with actionMethod properly defined.

My unit test looks like below

const functionA = function() { return; }
const functionB = function() { return; }
test('it can do something', function(assert) {
    let controller = this.subject();
    // I don't want the real functions to run 
    controller.set('functionA', functionA);
    controller.set('functionB', functionB);
    controller.send('actionMethod', '');
    // raises TypeError: this.functionA is not a function

    // this doesn't work etiher
    // controller.functionB = functionB;
    // controller.functionA = functionA;
    // controller.actions.actionMethod();
}

Does anyone have any ideas on how I can replace those functions in the testing environment? Or perhaps, is there a better way to test this functionality or set up my controller?


Solution

  • To replace the functions of the controller in the unit test, you can pass parameter to the this.subject() function:

     let controller = this.subject({
         functionA(){
             //this function overriddes functionA
         },
         functionB(){
             //this function overriddes functionB
         },
     });
    

    Look at the sample twiddle.

    This method is especially useful for replacing the injected service of the controllers.