Testing controller with resolve dependencies

315 views Asked by At

I'm trying to unit test a controller which relies on resolve keys using Jasmine. I am also using the controllerAs syntax. The routing code is as follows:

$routeProvider.when('/questions', {
    templateUrl: 'questions/partial/main_question_viewer/main_question_viewer.html',
    controller:'MainQuestionViewerCtrl',
    controllerAs:'questionCtrl',
    resolve: {
        default_page_size: ['QuestionService', function (QuestionService) {
            //TODO Work out page size for users screen
            return 50;
        }],
        starting_questions: ['QuestionService', function (QuestionService) {
            var questions = [];
            QuestionService.getQuestions(1).then(
                function(response){
                    questions = response;
                }
            );
            return questions;
        }],
    },
});

The controller (so far):

angular.module('questions').controller('MainQuestionViewerCtrl',
[
    'QuestionService',
    'starting_questions',
    'default_page_size',


    function (QuestionService, starting_questions, default_page_size) {

        var self = this;

        //Model Definition/Instantiation
        self.questions = starting_questions;
        self.page_size = default_page_size;
        self.filters = [];

        //Pagination Getters (state stored by QuestionService)
        self.current_page = function(){
            return QuestionService.get_pagination_info().current_page_number;
        }
        self.page_size = function(page_size){
            if(page_size != null){
                QuestionService.set_page_size(page_size);
            }
            return QuestionService.get_page_size();
        }
    }
]
);

And the test code:

describe('MainQuestionViewerCtrl', function () {

//===============================TEST DATA=====================================
var allQuestionsResponsePage1 = {
    count: 4,
    next: "https://dentest.com/questions/?format=json&page=2&page_size=1",
    previous: null,
    results: [
        {
            id: 1,
            subtopic: {
                topic: "Math",
                name: "Algebra"
            },
            question: "if a=3 and b=4 what is a+b?",
            answer: "7",
            restricted: false
        }
    ]
};

beforeEach(module('questions'));
beforeEach(module('globalConstants')); //Need REST URL for mocking responses

var ctrl, qService;
var backend,baseURL;

//inject dependencies
beforeEach(inject(function ($controller, $httpBackend,REST_BASE_URL) {
    ctrl = $controller('MainQuestionViewerCtrl');
    backend = $httpBackend;
    baseURL = REST_BASE_URL;
}));

//inject QuestionService and set up spies
beforeEach(inject(function (QuestionService) {


    qService = QuestionService;
}));

//Convenience for adding query params to mocked requests
var buildParams = function (page, page_size) {
    var params = {
        format: 'json',
        page: page,
        page_size: page_size,
    };

    var keys = Object.keys(params).sort(); //how angular orders query params
    var returnString = '?' + keys[0] + '=' + params[keys[0]] +
        '&' + keys[1] + '=' + params[keys[1]] + '&' + keys[2] + '=' + params[keys[2]];
    return returnString;
};

describe('Instantiation',inject(function ($controller) {
    beforeEach(module($provide){
    beforeEach(inject(function ($controller) {
        //Make a mock call to the server to set up state for the QuestionService
        backend.expectGET(baseURL + '/questions/' + buildParams(1, 1)).respond(200, allQuestionsResponsePage1);
        qService.getQuestions(1);
        backend.flush();

        //Now mock the result of resolve on route
        ctrl = $controller('MainQuestionViewerCtrl', {
            default_page_size: 1,
            starting_questions: allQuestionsResponsePage1,
        });
    }));

    it('should start with the first page of all the questions pulled down', function () {
        expect(qService.questions).toEqual(allQuestionsResponsePage1);
    });

    it('should start on page 1', function () {
        expect(qService.current_page).toEqual(1);
    });

    it('should start with the page size set to the default passed in',function(){
        expect(qService.page_size).toEqual(1);
    })
}));

When trying to run the tests, Angular is complaining that it cant resolve starting_questions or default_page_size because the providers for them aren't known.

It worth pointing out that the reason for mocking the HTTP request for the QuestionService is that it builds pagination info based on the response, which the controller will then access to determine the paginator size/numbers in the UI.

1

There are 1 answers

0
MichaelJK On

Solved. I was instantiating the controller in the outer describe without passing in mock values for the resolve key dependecies. That was causing the error: the method of instantiating the controller with the mock dependecies works fine.