угловое модульное тестирование компонента с помощью вызова службы http - PullRequest
0 голосов
/ 04 ноября 2019

Прежде всего, я новичок в угловых испытаниях, поэтому, пожалуйста, имейте это в виду. У меня есть компонент, который вызывает службу в методе ngOnInit . Метод выглядит следующим образом:

ngOnInit() {
    this.selectorService.category.subscribe(category => {
        if (!category) return;

        this.fieldService.list(category, false).subscribe(fields => {
            let rangeFields = fields.filter(field => !field.isSpecification);
            let specificationFields = fields.filter(field => field.isSpecification);

            this.fields = specificationFields;

            this.productService.listValidatedRangeProducts(category).subscribe(range => {
                if (!range.length) return;
                this.products = range;
                this.range = this.productModelService.mapProducts(rangeFields, range);
                this.saveForm = this.toFormGroup(range[0]);
            });
        });
    });
}

private toFormGroup(product: any): FormGroup {
    let group: any = {};

    this.fields.forEach(field => {
        group[field.name] = new FormControl(product[field.name]);
    });

    return new FormGroup(group);
}

У меня уже есть тесты для каждой настройки и работы службы. Теперь я хочу написать тесты для этого компонента. Я попробовал это:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpClientTestingModule } from '@angular/common/http/testing';

import { SharedModule } from '@shared';
import { SpecificationsSaveComponent } from './specifications-save.component';
import { ToastrModule, ToastrService } from 'ngx-toastr';

describe('SpecificationsSaveComponent', () => {
    let component: SpecificationsSaveComponent;
    let fixture: ComponentFixture<SpecificationsSaveComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [ReactiveFormsModule, HttpClientTestingModule, SharedModule, ToastrModule.forRoot()],
            declarations: [SpecificationsSaveComponent],
            providers: [ToastrService],
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SpecificationsSaveComponent);
        component = fixture.componentInstance;
        component.range = [
            {
                gtin: 0,
            },
            {
                gtin: 1,
            },
        ];

        component.fields = [
            {
                id: 0,
                canCopy: false,
                categoryId: 'cameras',
                dataType: 0,
                display: false,
                isSpecification: true,
                name: 'gtin',
                order: 0,
                required: true,
            },
        ];
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });

    it('should save and get next', () => {
        expect(component.saveForm.controls['gtin'].value).toBe(1);
    });

    it('should save and get reset', () => {
        expect(component.saveForm.controls['gtin'].value).toBeNull();
    });
});

В основном я пытался установить общие свойства, но это не работает. Я получаю эту ошибку:

TypeError: Невозможно прочитать свойство 'controls' неопределенного

Я подозреваю, что существует геттер, который выглядит следующим образом:

// convenience getter for easy access to form fields
get f() {
    return this.saveForm.controls;
}

saveForm должен быть создан в методе ngOnInit , как вы можете видеть из этой строки:

this.saveForm = this.toFormGroup(range[0]);

Итак, похоже, что янужно сделать макет selectorService , fieldService и productService , прежде чем я смогу продолжить. Может кто-нибудь показать мне, как это сделать?

Вот полный компонент:

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

import { Field } from '@models';
import { SelectorService, ProductModelService } from '@core';
import { ProductService, FieldService } from '@services';

@Component({
    selector: 'app-specifications-save',
    templateUrl: './specifications-save.component.html',
    styleUrls: ['./specifications-save.component.scss'],
})
export class SpecificationsSaveComponent implements OnInit {
    range: any[];
    saveForm: FormGroup;
    fields: Field[];
    submitted: boolean = false;

    private products: any[];

    constructor(
        private fieldService: FieldService,
        private productModelService: ProductModelService,
        private productService: ProductService,
        private selectorService: SelectorService,
    ) {}

    ngOnInit() {
        this.selectorService.category.subscribe(category => {
            if (!category) return;

            this.fieldService.list(category, false).subscribe(fields => {
                let rangeFields = fields.filter(field => !field.isSpecification);
                let specificationFields = fields.filter(field => field.isSpecification);

                this.fields = specificationFields;

                this.productService.listValidatedRangeProducts(category).subscribe(range => {
                    if (!range.length) return;
                    this.products = range;
                    this.range = this.productModelService.mapProducts(rangeFields, range);
                    this.saveForm = this.toFormGroup(range[0]);
                });
            });
        });
    }

    // convenience getter for easy access to form fields
    get f() {
        return this.saveForm.controls;
    }

    onSubmit(): void {
        this.submitted = true;

        if (this.saveForm.invalid) {
            return;
        }

        let categoryId = this.fields[0].categoryId;
        let product = {
            categoryId: categoryId,
        };

        let valid = true;
        this.fields.forEach(field => {
            let value = this.f[field.name].value;
            if (valid) {
                valid = !!value;
            }
            product[field.name] = value;
        });

        console.log(this.fields);
        console.log(product);
        console.log(valid);

        // TODO: save the product

        if (valid) {
            let gtin = product['gtin'];
            let index = 0;

            this.range.forEach((item, i) => {
                if (item.gtin !== gtin) return;
                index = i;
            });

            console.log(gtin);
            console.log(index);

            this.saveForm = this.toFormGroup(this.range[index + 1]);
            this.range.splice(index, 1);
        }

        // TODO: reset the form
    }

    private toFormGroup(product: any): FormGroup {
        let group: any = {};

        this.fields.forEach(field => {
            group[field.name] = new FormControl(product[field.name]);
        });

        return new FormGroup(group);
    }
}

1 Ответ

0 голосов
/ 06 ноября 2019

Не полное решение, но что-то вроде этого ... вам все равно нужно будет обслуживать продукт. Я использую Жасмин для создания макетов.

beforeEach(async(() => {
    //Setup mock selectorService
    const selectorService = {
        category: new BehaviorSubject<Category>(new Category()) //new Cateogry() should be whatever you want category to return
    }
    //Setup mock service with one function, 'list'
    const fieldService = jasmine.CreateSpyObj('fieldService', ['list']) //Create fieldService mock with one function 'list'

    fieldService.list.and.returnValue(of(fields)); //Not sure what type of object should be returned here... whatever type of object is returned form fieldService.list()

    TestBed.configureTestingModule({
        imports: [ReactiveFormsModule, HttpClientTestingModule, SharedModule, ToastrModule.forRoot()],
        declarations: [SpecificationsSaveComponent],
        providers: [ToastrService, {provide: FieldService, useValue: fieldService}, {provide: SelectorService, useValue: selectorService}],
    }).compileComponents();
}));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...