Angular manipulate service value inside test

93 Views Asked by At

I'm trying to manipulate the service return value in my test and attach that value to components field.

So I mock myService inside the Test1 and manipulate its value as true so that it always returns true. With the call fixture.detectChanges(); I invoke the this.myService.getProperty('param'); inside the PageComponent which should return true and make the value of myField also true. But it doesn't. The value of the field is still false. Test1 fails ofcourse.

I don't undestand what happens. Why can I just define the return value true inside the test and make the components value by that?

Test

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { anything, instance, mock, reset, verify, when } from 'ts-mockito';
import { MyService } from '../services/myservice.service';

describe('Test', () => {
    let component: PageComponent;
    let fixture: ComponentFixture<PageComponent>;
    let myServiceMock: myService = mock(MyService);

    describe('PageComponent', () => {
        beforeEach(() => {
            TestBed.configureTestingModule({
                imports: [],
                declarations: [PageComponent],
                schemas: [NO_ERRORS_SCHEMA],
                providers: [
                    { provide: myService, useValue: instance(myServiceMock) },
                ]
            }).compileComponents();

            fixture = TestBed.createComponent(PageComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
        });

        afterEach(() => {
            reset(myServiceMock);
        });

        it('Test1 - property should be true', () => {
            when(myServiceMock.getProperty(anything())).thenReturn(true);
            fixture.detectChanges();
            verify(myServiceMock.getProperty(anything())).once();
            expect(component.isCountryInfoVisible).toBeTrue();
            // Test Failed
            // Expected value to be true:
            //  true
            // Received:
            //  false
        });
    });
});

PageComponent

export class PageComponent implements OnInit {
    myField: boolean;

    constructor(private myService: MyService) {}

    ngOnInit(): void {
        this.myField = this.myService.getProperty('param');
    }
}

MyService

@Injectable()
export class MyService {

    private properties: Map<string, string> = new Map<string, string>();

    constructor() { }

    public getProperty(key: string): string {
        return this.properties.get(key);
    }

    ....
}
1

There are 1 best solutions below

0
On

Thanks to @EstusFlask I've figured out what happens;

My service call is inside ngOnInit which gets already invoked by the first fixture.detectChanges();. In that case the second fixture.detectChanges(); doesn't have any effect at all because it never get invoked again.

Solution: move the when(myServiceMock.getProperty(anything())).thenReturn(true); just above the first fixture.detectChanges(); like:

fixture = TestBed.createComponent(PageComponent);
component = fixture.componentInstance;

when(myServiceMock.getProperty(anything())).thenReturn(true);

fixture.detectChanges();