Manoj Masakorala
Manoj Masakorala

Reputation: 446

Unit Test Resolve Block in Angular component

Does anyone know how to unit test resolve block items in a routed component? It would be great if anyone can test courseDetails in the resolve block as an example.

(function() {
    'use strict';

    angular
        .module('writingsolutionsComponents')
        .component('courseSettings', {
            bindings: {
                newCourseForm: '<',
                courseDetails: '<',
                timezones: '<',
                citations: '<',
                disciplines: '<'
            },
            templateUrl: 'course-settings/course-settings.html',
            controller: 'CourseSettingsController'
        })
        .config(stateConfig);

    stateConfig.$inject = ['$stateProvider'];

    function stateConfig($stateProvider, $urlRouterProvider) {
        $stateProvider.state('course-settings', {
            parent: 'app',
            url: '/:courseId/course-settings',
            data: {
                pageTitle: "Hello World"
            },
            views: {
                'content@': {
                    component: 'courseSettings'
                }
            },
            resolve: {
                courseDetails: function(CourseService, $stateParams) {
                    return CourseService.get($stateParams.courseId);
                },
                timezones: function(TimezoneService) {
                    return TimezoneService.getTimeZones();
                },
                citations: function(CitationService) {
                    return CitationService.getCitations();
                },
                disciplines: function(DisciplineService) {
                    return DisciplineService.getAllDisciplines();
                }


                }
            }
        });
    }
})();

I tried following and it didn't workout for me.

CourseServiceMock = {
    get: function () {
      return $q.resolve({courseId: "32432535",                                                        title: "Communication"});
    }
  };
  spyOn(CourseServiceMock , 'get').and.callThrough();

  expect(CourseServiceMock .get).toHaveBeenCalled()

Upvotes: 2

Views: 863

Answers (1)

Aluan Haddad
Aluan Haddad

Reputation: 31823

Do not test your framework(s). Here that means do not test ui-router, it is known to work correctly. Specifically, we know it is going to call the registered resolve functions.

If you wish to test the resolve function itself, it is actually quite simple. We just need to make the function available to test. We can actually test this function without launching a web browser or doing anything fancy.

Here is an example that uses a test library called blue-tape* to run the test using NodeJS, you can adapt it to use Jasmine if you must.

// tests.js
const test = require("blue-tape");

test("courseDetails resolve retrieves the course based on route/:courseId", async t => {
  // arrange
  const courses = [{courseId: "32432535", title: "Communication"}];
  const mockCourseService = {
    get(id) {
      return Promise.resolve(courses.find(course => course.id === id));
    }
  };
  const mock$stateParams = {courseId: "32432535"};

  // act
  const result = await courseDetails(mockCourseService, mock$stateParams);

  // assert
  t.equal(result.courseId, courses[0].courseId);
});

To get this working, run

npm install --save-dev blue-tape

And then run

node test.js

The benefit is that your test does not depend on ui-router or even AngularJS and that it just tests what you care about, your business logic.

Note, this test itself is a bit arbitrary.

*I am using blue-tape instead of tape here because it makes testing asynchronous functions very simple as it automatically handles any function that returns a thennable.

Upvotes: 1

Related Questions