Я сделал некоторые обновления в Angular-компоненте, и он сломал некоторые юнит-тесты. Все тестовые спецификации нарушены, поэтому мне кажется, что это связано с инициализацией в вызовах beforeEach
. Я пытался исследовать проблему всесторонне, но не имел никакого успеха.
Ошибка, которую я получаю при запуске своих модульных тестов:
TypeError: Cannot read property 'subscribe' of undefined
Единственные звонки на subscribe
:
this.ruleDataFieldOption$.subscribe
...
this.submitted$.subscribe
...
this.dataFieldControl.valueChanges.subscribe
Я попытался явно инициализировать ruleDataFieldOption$
, установив его на of(mockRuleDataFields)
, но это не сработало. Я также попытался переместить блок кода из второго вызова beforeEach
в обещание асинхронного вызова beforeEach
(т. Е. .compileComponents().then( () => {...} )
, и это тоже не сработало.
клиент-правила-condition.component.spec.ts
const mockDataFieldService = {
getRuleDataFields: () => {}
} as RuleDataFieldService;
const mockStore = {
select: td.function('.select'),
dispatch: td.function('.dispatch'),
pipe: td.function('.pipe'),
} as Store<any>;
let dispatch;
let pipe;
const mockConfigService = {
getConfiguration: td.func(() => {
return mockNotificationConfig
})
} as ConfigService;
const mockNotificationConfig = {
Env: null,
apiBaseUrl: 'blah'
} as MclNotificationConfig;
const mockRuleDataFields: RuleDataFieldDefinition[] = [
{name: 'data field 1', dataFieldId: 'mock data field guid', category: 'mock category'} as RuleDataFieldDefinition
];
fdescribe('ClientRulesConditionComponent', () => {
let component: ClientRulesConditionComponent;
let fixture: ComponentFixture<ClientRulesConditionComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ClientRulesConditionComponent ],
imports: [ReactiveFormsModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
{provide: Store, useFactory: () => mockStore},
{provide: RuleDataFieldService, useValue: mockRuleDataFields},
HttpClientTestingModule,
// {provide: ConfigService, useFactory: () => mockConfigService},
// {provide: MclNotificationConfig, useFactory: () => mockNotificationConfig},
// HttpHandler, HttpClient
]
})
.compileComponents();
}));
beforeEach(() => {
dispatch = spyOn(mockStore, 'dispatch');
pipe = spyOn(mockStore, 'pipe').and.callThrough();
fixture = TestBed.createComponent(ClientRulesConditionComponent);
component = fixture.componentInstance;
const fb: FormBuilder = new FormBuilder();
component.conditionForm = fb.group({
name: fb.control('', [Validators.required]),
triggerWhen: fb.control('', [Validators.required]),
conditions: fb.array([
fb.group({
dataField: fb.control('df1'),
conditionToMatch: fb.control('ctm1'),
value: fb.control('v1')
}),
fb.group({
dataField: fb.control('df2'),
conditionToMatch: fb.control('ctm2'),
value: fb.control('v2')
})
])
});
component.indexInConditionArray = 1;
component.submitted$ = of(false);
component.ruleDataFieldOption$ = of(mockRuleDataFields);
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
// Confirm conditionToMatch and dataField get actions have been dispatched
expect(dispatch).toHaveBeenCalledTimes(2);
// Confirm that we load the correct set of form controls and they have the correct value associated with them
const conditionsArray = component.conditionForm.controls['conditions'] as FormArray;
const conditionGroup = conditionsArray.at(component.indexInConditionArray) as FormGroup;
expect(component.dataFieldControl).toEqual(conditionGroup.controls['dataField'] as FormControl);
expect(component.dataFieldControl.value).toEqual('df2');
expect(component.matchingConditionControl).toEqual(conditionGroup.controls['conditionToMatch'] as FormControl);
expect(component.matchingConditionControl.value).toEqual('ctm2');
expect(component.valueControl).toEqual(conditionGroup.controls['value'] as FormControl);
expect(component.valueControl.value).toEqual('v2');
// Confirm the conditionToMatch and dataField selectors were wired up
expect(pipe).toHaveBeenCalledTimes(2);
// Confirm the expected value for the 'submitted' flag got emitted
expect(component.submitted).toBeFalsy();
});
});
.
.
.
клиент-правила-condition.component.ts
@Component({
selector: 'nd-client-rules-condition',
templateUrl: './client-rules-condition.component.html',
styleUrls: ['./client-rules-condition.component.scss']
})
export class ClientRulesConditionComponent implements OnInit {
@Input() conditionForm: FormGroup;
@Input() indexInConditionArray: number;
@Input() submitted$: Observable<boolean>;
@Output() removeCondition: EventEmitter<number> = new EventEmitter();
conditionToMatchOption$: Observable<ConditionToMatch[]>;
valueControl: FormControl;
matchingConditionControl: FormControl;
dataFieldControl: FormControl;
private static NPI_DATA_FIELD_GUID: string;
validValuePattern: string;
invalidValueError: string;
// Emits the candidate rule fields that eventually come back from the database.
// The 'data fields' combo box in the markup is wired up to this.
ruleDataFieldOption$: Observable<RuleDataFieldDefinition[]>;
// Tracks whether the parent form has been submitted.
submitted: boolean;
constructor(private _store: Store<state.AppState>) { }
ngOnInit() {
this._store.dispatch(new GetConditionToMatchOptions(''));
// Dispatch Action that causes the rule-data-field options to get retrieved from the server and slammed into the global state.
this._store.dispatch(new GetRuleDataFieldsOptions(''));
this.conditionToMatchOption$ = this._store.pipe(select(getConditionToMatchOption));
// Wire up the selector that cause the rule-data-field options to get pulled from the global state when they are set/updated
this.ruleDataFieldOption$ = this._store.pipe(select(getRuleDataFieldsSelector));
// Load GUID for NPI field to use to distinguish between different Data Field dropdown items to apply different validation in Value To Match
this.ruleDataFieldOption$.subscribe(dataFields => {
if (ClientRulesConditionComponent.NPI_DATA_FIELD_GUID == null) {
for (let df of dataFields) {
if (df.name.toLowerCase().includes('npi') || df.name.toLowerCase().includes('national provider identifier')) {
ClientRulesConditionComponent.NPI_DATA_FIELD_GUID = df.dataFieldId.toUpperCase();
break;
}
}
}
});
.
.
.
Я уверен, что это что-то незначительное, и мне просто нужно пройти мои модульные тесты.