Я написал много модульных тестов для проверки наблюдаемых, но по какой-то причине этот тест не работает, как другие, которые я написал, но я не понимаю, в чем проблема.
Я хотел бы, чтобы макет для ChangePasswordFacade.successful$ возвращал Observable, который возвращает true. Несмотря на то, что я ранее использовал издевательскую стратегию ниже, она не работает. Я попытался внедрить ChangePasswordFacade в тест. Я попытался использовать функцию mock Success$ в useValue провайдера TestBed. И я попробовал подход ниже. Все они выдают успешный $ как ложный. Как я могу издеваться над этим по-другому, чтобы вернуть true?
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PasswordChangeModalComponent } from './password-change-modal.component';
import { ReactiveFormsModule } from '@angular/forms';
import { PasswordChangeFormComponent } from '../../..';
import { DefaultPopoverComponent } from '@bis-angular/shared-components/pattern-library';
import { Store, StoreModule } from '@ngrx/store';
import {
ChangePasswordFacade,
UserInformationFacade,
changePasswordInitialState,
CHANGEPASSWORD_FEATURE_KEY,
changePasswordReducer
} from '@bis-angular/users';
import { configureTestSuite } from 'ng-bullet';
import { of } from 'rxjs';
describe('PasswordChangeModalComponent', () => {
let component: PasswordChangeModalComponent;
let fixture: ComponentFixture<PasswordChangeModalComponent>;
const childDefaultPopoverComponent = jasmine.createSpyObj('DefaultPopoverComponent', ['hideModal', 'showModal']);
const childPasswordChangeFormComponent = jasmine.createSpyObj('PasswordChangeFormComponent', ['setFormControlsToEmpty']);
const changePasswordFacadeSpy = jasmine.createSpyObj('ChangePasswordFacade', ['resetState']);
configureTestSuite(() => {
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule,
StoreModule.forRoot({}),
StoreModule.forFeature(CHANGEPASSWORD_FEATURE_KEY, changePasswordReducer, {
initialState: changePasswordInitialState
})
],
declarations: [PasswordChangeFormComponent, DefaultPopoverComponent, PasswordChangeModalComponent],
providers: [Store, UserInformationFacade, ChangePasswordFacade]
});
});
beforeEach(() => {
fixture = TestBed.createComponent(PasswordChangeModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
component.defaultPopoverComponent = childDefaultPopoverComponent;
component.watchSuccessful = { unsubscribe: () => {} };
spyOn(component.watchSuccessful, 'unsubscribe');
const service = TestBed.get(ChangePasswordFacade);
spyOn(service, 'successful$').and.returnValue(of(true));
});
describe('showPasswordChangeModal function ', () => {
it('should call showModal and then not hide if not successful ', () => {
spyOn(component, 'hidePasswordChangeModal');
component.successful$.subscribe((successful: boolean) => {
expect(component.hidePasswordChangeModal).toHaveBeenCalled();
expect(changePasswordFacadeSpy.resetState).toHaveBeenCalled();
expect(component.watchSuccessful.unsubscribe).toHaveBeenCalled();
});
component.showPasswordChangeModal();
expect(childDefaultPopoverComponent.showModal).toHaveBeenCalled();
});
});
});
import { Injectable } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { ChangePasswordPartialState } from './change-password.reducer';
import { changePasswordQuery } from './change-password.selectors';
import { ChangePassword, ChangePasswordResetState } from './change-password.actions';
import { NewPassword } from '@bis-angular/users';
@Injectable()
export class ChangePasswordFacade {
successful$ = this.store.pipe(select(changePasswordQuery.getSuccessful));
initiated$ = this.store.pipe(select(changePasswordQuery.getInitiated));
constructor(private store: Store<ChangePasswordPartialState>) {}
changePassword(newPassword: NewPassword, userId: string) {
this.store.dispatch(new ChangePassword(newPassword, userId));
}
resetState() {
this.store.dispatch(new ChangePasswordResetState());
}
}





Поскольку вы хотите получить доступ к successful$, который определен на уровне класса ChangePasswordFacade.
что-то типа:
export class ChangePasswordFacade{
successful$:observable // ... something like this
}
Вы должны попробовать useValue:
configureTestSuite(() => {
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule,
StoreModule.forRoot({}),
StoreModule.forFeature(CHANGEPASSWORD_FEATURE_KEY, changePasswordReducer, {
initialState: changePasswordInitialState
})
],
declarations: [PasswordChangeFormComponent, DefaultPopoverComponent, PasswordChangeModalComponent],
providers: [Store, UserInformationFacade,
{provide: ChangePasswordFacade , useValue:
{
successful$ : of(true)
}
}'
]
});
});
Спасибо за предложение. Я попробовал именно тот подход, который вы предложили выше, как я отметил в своем первоначальном описании проблемы. Это не работает.
@ user372225: какие значения вы получили от succeessful$, когда попробовали мое предложение?
привет @ShashankVivek, я получаю «ложное» значение для успешного $, используя ваше предложение.
@ user372225, даже когда вы настраиваете его of(true)true? какая-то переменная, кажется, манипулирует ею тогда
вот как я это сделал: я использовал хранилище для отправки действия, чтобы изменить успешное $ на true. теперь это интеграционный тест, а не модульный тест.
import { ChangePasswordFacade, UserInformationFacade } from '@bis-angular/users';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { StoreModule, Store } from '@ngrx/store';
import { PasswordChangeModalComponent, PasswordChangeFormComponent } from '../../..';
import * as fromFeature from '@bis-angular/users';
import { ReactiveFormsModule } from '@angular/forms';
import { configureTestSuite } from 'ng-bullet';
import { DefaultPopoverComponent } from '@bis-angular/shared-components/pattern-library';
describe('PasswordChangeModalComponent', () => {
let component: PasswordChangeModalComponent;
let fixture: ComponentFixture<PasswordChangeModalComponent>;
let store: Store<fromFeature.ChangePasswordState>;
const childDefaultPopoverComponent = jasmine.createSpyObj('DefaultPopoverComponent', ['hideModal', 'showModal']);
const childPasswordChangeFormComponent = jasmine.createSpyObj('PasswordChangeFormComponent', ['setFormControlsToEmpty']);
configureTestSuite(() => {
TestBed.configureTestingModule({
imports: [
StoreModule.forRoot({}),
ReactiveFormsModule,
StoreModule.forFeature(fromFeature.CHANGEPASSWORD_FEATURE_KEY, fromFeature.changePasswordReducer, {
initialState: fromFeature.changePasswordInitialState
})
],
declarations: [PasswordChangeModalComponent, DefaultPopoverComponent, PasswordChangeFormComponent],
providers: [ChangePasswordFacade, UserInformationFacade]
});
});
beforeEach(() => {
store = TestBed.get(Store);
spyOn(store, 'dispatch').and.callThrough();
fixture = TestBed.createComponent(PasswordChangeModalComponent);
component = fixture.componentInstance;
component.defaultPopoverComponent = childDefaultPopoverComponent;
component.watchSuccessful = { unsubscribe: () => {} };
spyOn(component.watchSuccessful, 'unsubscribe');
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
describe('showPasswordChangeModal function ', () => {
it('should call showModal and then hide if successful ', () => {
spyOn(component, 'hidePasswordChangeModal');
spyOn(component.changePasswordService, 'resetState');
const action = new fromFeature.ChangePasswordSuccessful({});
store.dispatch(action);
component.showPasswordChangeModal();
component.successful$.subscribe((successful: boolean) => {
expect(component.hidePasswordChangeModal).toHaveBeenCalled();
expect(component.changePasswordService.resetState).toHaveBeenCalled();
});
expect(childDefaultPopoverComponent.showModal).toHaveBeenCalled();
});
});
});
Вы случайно не объявляете
ChangePasswordFacadeв массиве provider декоратора@Componentдля определения классаPasswordChangeModalComponent? Если это так, вам нужно будет использовать overrideComponent для успешного внедрения фиктивного провайдера.