角单元使用http服务调用测试组件

时间:2019-11-04 09:58:52

标签: angular unit-testing

首先,我是角度测试的新手,所以请记住这一点。 我有一个在 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:无法读取未定义的属性“控件”

我怀疑这是因为有一个看起来像这样的吸气剂:

// convenience getter for easy access to form fields
get f() {
    return this.saveForm.controls;
}
如以下行所示,应在 ngOnInit 方法中创建

saveForm

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 :(得分:0)

这不是一个完整的解决方案,但是类似这样的事情……您仍然需要进行产品服务。我在这里使用Jasmine来创建模拟。

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();
}));