woutr_be
woutr_be

Reputation: 9722

Karma + Jasmine testing async methods

I have the following controller:

export default function($scope, $state, $http) {
    $scope.login = () => {
        $scope.loginFailed = false;

        const postReq: object = {
            method: 'POST',
            url: `/login`,
            data: {},
        }

        try {
            console.log('$scope.login');

            const response = await $http(postReq);

            console.log('login done');

            console.log('$state.go');

            $state.go('dashboard');

            return true;
        } catch(err) {
            console.error(err);
            $scope.loginFailed = true;

            return false;
        }
    };
}

I'm trying to test this method with Jasmine

it('change state to dashboard', async (done) => {
    $httpBackend.expectPOST('/login', undefined).respond(201, { rmId: 123123 });

    await $scope.login();
    expect($state.current.name).toBe('dashboard');
});

The results of my tests are as follows:

LOG: '$scope.login' PhantomJS 2.1.1 (Mac OS X 0.0.0) $scope.login change state to dashboard FAILED

Now it seems that Jasmine isn't waiting for the $http call to be completed. (This works fine when I manually test it in a browser)

Is there a better way to correctly test async methods?

Upvotes: 1

Views: 3709

Answers (2)

segito10
segito10

Reputation: 388

you don't need to do the await. you just need to flush the backend mock before expect test your login function must be change like this:

$scope.login = () => {
       return new Promise((resolve, reject) => {
          $scope.loginFailed = false;

        const postReq = {
            method: 'POST',
            url: `/login`,
            data: {},
        }

        const response = $http(postReq).then(
          (success) => {
              $state.go('dashboard');
              resolve(true);
            },
            (error) => {
               $scope.loginFailed = true;

            reject(false);
            });
       });
    };

And your test like :

it('change state to dashboard', async (done) => {
    const  backendMock = $httpBackend;
    backendMock.expectPOST('/login').respond(201, { rmId: 123123 });
    $scope.login().then((response) => {
      expect($state.current.name).toBe('dashboard');
      done();
    });
    backendMock.flush();

});

Upvotes: 2

codeLover
codeLover

Reputation: 2592

You need to use $httpBackend.flush(); before writing your assertions. Add this line before your expect statement. It should work..

Upvotes: 0

Related Questions