Jasmine spyOn service dependency

Discussão em 'Angular' iniciado por Stiley, Fevereiro 14, 2025.

  1. Stiley

    Stiley Guest

    I am having difficulty understanding jasmine spies for services with dependencies injected in constructor

    I have an Account service with Constructor

    constructor(private readonly api: ApiService,private readonly authorityService: AuthorityService) {}


    In the Account service I have a method that is using the authorityService, (set in the constructor), to check for a permission before returning a value

    public async getAccount(): Promise<Account | null> {
    if (this.authorityService.hasAuthority(Authority.PERM_ACCOUNT_READ)) {
    this.account = await this.api.get<Account>('/admin/rest/account');
    return this.account;
    }
    return null;
    }


    What I am trying to do is provide unit tests for the getAccount method. What I want is to ensure when authorityService.hasAuthority(Authority.PERM_ACCOUNT_READ) returns true or false

    In my test I have set up the following in my .spec.ts file

    stub the authService

    class authorityServiceStub{
    hasAuthority(str: string): boolean {
    return false;
    }
    }


    then in my describe block I have the following

    fdescribe('AccountService', () => {
    let service: AccountService;
    let httpTestingController:HttpTestingController
    let authorityServiceDependency:AuthorityService;

    /**
    * Sets up the testing module before each test case.
    */
    beforeEach(waitForAsync(() => {

    TestBed.configureTestingModule({
    imports: [],
    providers: [provideHttpClient(),
    provideHttpClientTesting(),
    AccountService,{
    provide: AuthorityService,
    useClass: authorityServiceStub
    }
    ],
    })

    service = TestBed.inject(AccountService);
    authorityServiceDependency = TestBed.inject(AuthorityService);
    httpTestingController = TestBed.inject(HttpTestingController);
    }));


    in my first test where I want to ensure if the permission is false, my Account object from getAccount() in null

    it('should return null if not permissions and not forced', async() => {
    spyOn(authorityServiceDependency, 'hasAuthority').withArgs(Authority.PERM_ACCOUNT_READ).and.returnValue(false);
    const account = await service.getAccount();
    expect(account).toBeNull();
    expect(authorityServiceDependency.hasAuthority).toHaveBeenCalledWith(Authority.PERM_ACCOUNT_READ);
    const req = httpTestingController.match((request) =>
    request.url.includes("/admin/rest/account")
    );
    });


    This test passes

    but in the other case where I want to test when the permission is set and validate the account is not null I have the following

    it('should return the account if the permissions are set', async() => {
    const accountData = {firstName: 'Test',lastName:"tester"} as Account;
    spyOn(authorityServiceDependency, 'hasAuthority').withArgs(Authority.PERM_ACCOUNT_READ).and.returnValue(true);
    spyOn(service, 'getAccount').and.returnValue(Promise.resolve(accountData));
    service.getAccount().then((account) => {
    expect(account).not.toBeNull();
    expect(account?.firstName).toEqual("Test");
    expect(account?.lastName).toEqual("tester");
    expect(service.getAccount).toHaveBeenCalled();

    });
    expect(authorityServiceDependency.hasAuthority).toHaveBeenCalledWith(Authority.PERM_ACCOUNT_READ);
    const req = httpTestingController.match((request) =>
    request.url.includes("/admin/rest/account")
    );
    });


    the expect expect(authorityServiceDependency.hasAuthority).toHaveBeenCalledWith(Authority.PERM_ACCOUNT_READ);

    is failing with message


    Expected spy hasAuthority to have been called with: [ 'PERM_ACCOUNT_READ' ] but it was never called. at at UserContext. (src/app/core/services/account/account.service.spec.ts:86:53) at Generator.next () at asyncGeneratorStep (node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:3:1) at _next (node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:17:1)
    ​

    I know its something I'm doing incorrectly but for the life of me I cannot get this to work as I want. Not clear is setting up the mock class in my test is correct approach.. seems clunky but I read this approach somewhere on the internet and it seems to make sense but I'm kinda out of my element here and would appreciate any insight / guidance

    Continue reading...

Compartilhe esta Página