简体   繁体   中英

Angular2 / Jasmine: Spy on unit testing methods doesn't see called method

I've got a problem with detecting spy have called an function. It's a unit test of service. I've tried two different approaches with TestBed.get on method (in ' it should check only status') and spy on injected dummy class ("in it should login unknown to facebook"), but neither of them doesnt seem to work I've done some print to see if method is used, and there are shown. Here's a spec file:

import { TestBed, inject, async } from '@angular/core/testing';

import {FacebookServiceMock } from './../test-helpers/facebook-service-mock';
import { SocialsServiceDummy } from './../test-helpers/socialsServiceDummy';
import { ErrorDouble } from './../test-helpers/errorDouble';

import { ErrorsService } from './../../app/services/errors.service';
import { social_config, SocialConfig, SOCIAL_CONFIG } from './../../app/socials/social-config';
import { SocialsService } from './../../app/services/socials.service';
import { FacebookLoginService } from './../../app/services/facebook-login.service';
import { FacebookService } from 'ngx-facebook';

describe('Facebook-login-service test', () => {
    let socialsServiceSpy: any;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            providers: [
                FacebookLoginService,
                { provide: FacebookService, useFactory: () => { return new FacebookServiceMock() }},
                { provide: SocialsService, useFactory: () => {  return new SocialsServiceDummy() }},
                { provide: ErrorsService, useFactory: () => { return new ErrorDouble() } },
                { provide: social_config, useValue: SOCIAL_CONFIG }
            ]
        });


    });

    beforeEach(() => {
        socialsServiceSpy = TestBed.get(SocialsService);
        spyOn(socialsServiceSpy, 'updateAccount');

    });

    afterEach(()=>{
        TestBed.resetTestingModule();

    });

    it('should login unknown to facebook',
        async(inject([FacebookLoginService, FacebookService, SocialsService, ErrorsService, social_config], (facebookLoginService, FacebookServiceMock, SocialsServiceDummy, ErrorDouble, SOCIAL_CONFIG) => {
                let mockReturn = {
                    status: "unknown",
                    authResponse: {
                        userID: '123456',
                        accessToken: 'token',
                        expiresIn: 3600
                    }
                };

                spyOn(FacebookServiceMock, 'getLoginStatus').and.returnValue(Promise.resolve(mockReturn));
                spyOn(SocialsServiceDummy, 'addNewSocialAccount').and.callThrough();
                spyOn(facebookLoginService, 'loginToFacebook').and.callThrough();

                facebookLoginService.checkLoginStatus();
                expect(facebookLoginService.loginToFacebook).toHaveBeenCalled();
                expect(SocialsServiceDummy.addNewSocialAccount).toHaveBeenCalledWith('facebook', mockReturn.authResponse.userID, mockReturn.authResponse.accessToken, mockReturn.authResponse.expiresIn);
            })
        ));

    it('should check only status',
        async(inject([FacebookLoginService, FacebookService, SocialsService, ErrorsService, social_config], (facebookLoginService, FacebookServiceMock, SocialsServiceDummy, ErrorDouble, SOCIAL_CONFIG) => {
                let mockReturn = {
                    status: "connected",
                    authResponse: {
                        userID: '123456',
                        accessToken: 'token',
                        expiresIn: 3600
                    }
                };
                spyOn(FacebookServiceMock, 'getLoginStatus').and.returnValue(Promise.resolve(mockReturn));
               // spyOn(SocialsServiceDummy, 'updateAccount').and.callThrough();

                facebookLoginService.checkLoginStatus();
                expect(socialsServiceSpy.updateAccount).toHaveBeenCalledWith('facebook', mockReturn.authResponse.userID, mockReturn.authResponse.accessToken, mockReturn.authResponse.expiresIn);


            })
        ));
});

The FacebookLoginService looks like this:

/**
 * Created by Daniel on 2017-06-19.
 */
import { Injectable, Inject } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { FacebookService, LoginResponse, LoginOptions } from 'ngx-facebook';
import { ErrorsService } from './errors.service';
import { social_config, SocialConfig } from './../socials/social-config';
import { NewSocialAccount } from './../shared/models/new-social-account';
import { SocialsService } from "./socials.service";

@Injectable()

export class FacebookLoginService {
    private loginOptions : LoginOptions = {
        scope: this.socialConfig.facebook.scope
    }

    private attemptToLogin =  new Subject<boolean>()
    private newSocialAccount =  new Subject<any>();

    login$ = this.attemptToLogin.asObservable();
    newSocial$ = this.newSocialAccount.asObservable();

    constructor(
        private facebookService: FacebookService,
        private socialsService: SocialsService,
        private errorsService: ErrorsService,
        @Inject(social_config) private socialConfig: SocialConfig
    ) {}

    initSocials() : void {
        this.facebookService.init({appId: this.socialConfig.facebook.appId, version: this.socialConfig.facebook.version});
    }

    checkLoginStatus() : void{
        this.facebookService.getLoginStatus().then(
            (res) => {
                if(res.status == "connected") {
                    const updatedAccount = this.createNewAccountObject('facebook', res.authResponse.userID, res.authResponse.accessToken, res.authResponse.expiresIn);
                    this.socialsService.updateAccount(updatedAccount).then(
                        () => {
                            this.attemptToLogin.next(true);
                        },
                        error => {
                            this.errorsService.startErrorAction(error);
                        }
                    )
                } else {
                   this.loginToFacebook();
                }
            },
            error => {
                alert('Unable to connect with Facebook. Please try later');
            }
        )
    }

    loginToFacebook() : void {
        this.facebookService.login(this.loginOptions).then(
            (res: LoginResponse) => {
                const newAccount = this.createNewAccountObject('facebook', res.authResponse.userID, res.authResponse.accessToken, res.authResponse.expiresIn);
                this.socialsService.addNewSocialAccount(newAccount).then(
                    (res) => {
                        this.confirmLoginNewSocialAccount(res, 'facebook');
                    },
                    error => {
                        this.errorsService.startErrorAction(error);
                    }
                )
            },
            error => {
                alert('Unable to connect with Facebook. Please try later');
            }
        )

    }

    logout(): void {
        this.facebookService.logout();
    }

    private createNewAccountObject(socialStr: string, userStr: string, tokenStr: string, expiresNr: number): NewSocialAccount {
            return {
                social: socialStr,
                userID: userStr,
                token: tokenStr,
                expires:  expiresNr
            };
        }

    private confirmLoginNewSocialAccount(response: any, accountType: string) {
        this.newSocialAccount.next({login: response.login, social: accountType});

    }
}

Here is dummy file from injected social service

import { SocialAccount} from './../../app/shared/models/social-account';
import { NewSocialAccount} from './../../app/shared/models/new-social-account';

export class SocialsServiceDummy {

    getSocials(): Promise<SocialAccount[]> {
      let socials =  [

      ];
      return Promise.resolve(socials);
    }

    addNewSocialAccount(newAccount: NewSocialAccount) : Promise<any>{
      let social4 = {login: 'facebook', userId: '1fsdf42343', token: 'some_token', expire: 3600};
      return Promise.resolve(social4);
    }

    deleteAccount(id: number): Promise<void> {
      return Promise.resolve(null);
    }

    updateAccount(account: SocialAccount ):  Promise<void>{
        return Promise.resolve(null);
    }

}

I've resigned from FacebookServiceMock and use it only as injected stub, and return result from spy. Error double and social_config are also stub.

I would be very glad for some help in what am I doing wrong

Cheers.

I used the spyOn differenty. Maybe this works:

let spy = spyOn(new Date(), 'toString');
expect(spy.calls.count()>0).toBeTruthy();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM