Изменение значения наблюдаемого, возвращаемого фиктивной службой для каждого теста в Angular / Jasmine / Redux - PullRequest
0 голосов
/ 14 января 2019

У меня есть сервис, который возвращает значения, предоставляемые селекторами ngrx. Компонент определяет этот сервис для получения данных. Я пишу модульные тесты для компонента, используя макет сервиса, и мне нужен сервис макета, чтобы возвращать разные значения для каждого модульного теста. Как мне этого добиться?

Компонент

@Component({
    selector: 'app-test',
    templateUrl: './test.component.html',
    providers: [TestService],

})
    export class TestComponent {

        test$ = this.testService.test$;
        test: number;

        constructor(private service: TestService) {
            service.test$.subscribe(test => this.test = test);
        }
    }

Услуги

export class TestService {

        test$ = this.store.select(getTestValueFromStore);

        constructor(private store: Store<any>){}
}

Попытка 1 (сбросить значение услуги): не работает

class MockTestService {
    **test$ = of(10);**
}

describe('TestComponent', () => {
    let testService: TestService;

    beforeEach((() => {
        // Define component service
        TestBed.overrideComponent(
            TestComponent,
            { set: { providers: [{ provide: TestService, useClass: MockTestService }] } }
        );

        TestBed.configureTestingModule({
            declarations: [TestComponent]
        })
            .compileComponents();
    }));

    beforeEach(async() => {
        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;
        testService = fixture.debugElement.injector.get(TestService);
        fixture.detectChanges();
    });

it('should do something when the value returned by the service is 20', fakeAsync(() => {

        **testService.test$ = of(20);**

        tick();

        expect(component.test).toEqual(20);
    }));
});

Попытка 2: использовать предметы. Карма бросает ошибку «Свойство next» не существует для типа «Observable» потому что TestService возвращает наблюдаемые, а не субъекты

class MockTestService {
        **test$ = new BehaviourSubject(10);**
    }

    describe('TestComponent', () => {
        let testService: TestService;

        beforeEach((() => {
            // Define component service
            TestBed.overrideComponent(
                TestComponent,
                { set: { providers: [{ provide: TestService, useClass: MockTestService }] } }
            );

            TestBed.configureTestingModule({
                declarations: [TestComponent]
            })
                .compileComponents();
        }));

        beforeEach(async() => {
            fixture = TestBed.createComponent(TestComponent);
            component = fixture.componentInstance;
            testService = fixture.debugElement.injector.get(TestService);
            fixture.detectChanges();
        });

    it('should do something when the value returned by the service is 20', fakeAsync(() => {

            **testService.test$.next(20);**

            tick();

            expect(component.test).toEqual(20);
        }));
    });

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Вы сказали в своем вопросе, что хотите, чтобы «фиктивная служба возвращала разные значения для каждого модульного теста». Для этого вам нужно будет внести некоторые изменения в способ определения вашего компонента.

  1. Наиболее важным изменением является перемещение подписки в ngOnInit () и из конструктора для вашего компонента. Если вы сделаете это, то сможете контролировать, когда сработает подписка, в противном случае она сработает при создании компонента, что очень затруднит возврат различных значений для каждого модульного теста.

  2. Как только это будет сделано, вам нужно быть осторожным, когда вы звоните fixture.detectChanges(). Это потому, что это выполнит ngOnInit(), который выполнит подписку и сохранит значение, возвращенное из Наблюдаемого в component.test. Обратите внимание, что, поскольку вы используете of(), он просто издаст один раз, а затем завершится. Он не будет излучать снова, если вы введете новое значение в testService.test$.

  3. После того, как вы настроите эту настройку, вы можете изменить значение testService.test$ ДО того, как вы вызовете fixture.detectChanges и сделаете значения как хотите.

Я настроил StackBlitz , чтобы продемонстрировать это, изменяя ваш код как можно меньше, чтобы он работал. Есть два теста, каждый из которых проверяет разные значения.

Надеюсь, это поможет!

0 голосов
/ 14 января 2019

Попробуйте что-то вроде этого

describe('TestComponent', () => {
    beforeEach((() => {
        TestBed.configureTestingModule({
            declarations: [TestComponent],
            providers: [
              { provide: TestService, useValue: { test$: of(20) } }
            ]
        })
            .compileComponents();
    }));

    beforeEach(async() => {
        fixture = TestBed.createComponent(TestComponent);
        component = fixture.componentInstance;
        testService = fixture.debugElement.injector.get(TestService);
        fixture.detectChanges();
    });

   it('should do something when the value returned by the service is 20', () => {
        expect(component.test).toEqual(20);
    });
});

Вам не нужно использовать fakeAsync, потому что of() генерирует синхронно.

Также, пожалуйста, рассмотрите возможность подписки на наблюдаемое в ngOnInit hook. Конструктор должен использоваться только для внедрения зависимостей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...