Angular testing mock subscribed property
Asked Answered
D

2

6

I have a service with 2 properties:

Service

...
public usernameAnnounced;
private username: Subject<string> = new Subject<string>();

constructor() {
    super();
    this.usernameAnnounced = this.username.asObservable();
}

On my component I want to subscribe to the property:

Component

    public ngOnInit(): void {
    this.service.usernameAnnounced.subscribe((username: string) => {
        this.username = NavbarComponent.capitalizeFirstLetter(username);
    });
}

I emit to the username on another comp. but its irrelevant for this question. Now I want to mock usernameAnnounced but I have difficulties with it. I tried it with spyOn and it throws me a: 'usernameAnnounced is not a function.' with spyOnProperties it throws me a : 'property is not a getter'.

Tested comp.

so far my approach looks as follows:

    beforeEach(async(() => {
    TestBed.configureTestingModule({
        ...
        declarations: [NavbarComponent],
        providers: [
            ...,
            {provide: service, useValue: authenticationMock}
            ]
        })
        .compileComponents();

    fixture = TestBed.createComponent(NavbarComponent);
}));
...
    it('should render username',() => {
    const underTest = fixture.componentInstance;

    spyOnProperty(authenticationMock, 'usernameAnnounced').and.returnValue({
            subscribe: () => {'boboUser'}}); <== important part here

    underTest.ngOnInit();
    fixture.detectChanges();

    const compiled: HTMLElement = fixture.debugElement.nativeElement.querySelector('#userName');
    const rendered: string = compiled.textContent;

    expect(rendered).toMatch(`Logged in as: ${underTest.username}`);
});

Does someone has any hints?

Debussy answered 5/7, 2018 at 12:46 Comment(0)
D
11

I figured out the solution with: First of all creating a jasmine.spyObj like this:

    const authenticationMock: AuthenticationService = jasmine.createSpyObj('AuthenticationService',
    ['usernameAnnounced']);

Assign it to the mocked service: {provide: AuthenticationService, useValue: authenticationMock}. And it the unit test itself just assign the property with ur expected result:

const spy = TestBed.get(AuthenticationService);
    spy.usernameAnnounced = Observable.of('dummyUser');
Debussy answered 5/7, 2018 at 14:2 Comment(2)
Thanks for this, I wish I had found this anser 3 hours agoPalliasse
Actually the best approach I found in the last several hours!Nissa
H
3

I always had to build an Subject (or BehaviorSubject) on my mock.

class authenticationMock{ // is the mock of AuthenticationService
    public usernameAnnounced:Subject<string> = new Subject<string>();
}

...

// in Test
let authenticationService = TestBed.get(AuthenticationService)
...
authenticationService.next('myNewUser');

warm regards

Haphazard answered 5/7, 2018 at 12:57 Comment(1)
Thanks mate, with ur approach I got somehow 'undefined' as the result. But you led me in the right direction.Debussy

© 2022 - 2024 — McMap. All rights reserved.