【问题标题】:angular spectator mock Observable<string>角度观众模拟 Observable<string>
【发布时间】:2020-02-29 15:43:17
【问题描述】:

我正在尝试使用https://github.com/ngneat/spectator 编写一个(相当)复杂的测试 我有一个在 ngOnInit 中有 3 个 http 服务的组件。

其中两个很容易模拟,我可以通过两种方式(我认为):

const FieldServiceMock = {
    list: (categoryId: string, specificationOnly: boolean) =>
        of([
            {
                id: 0,
                canCopy: false,
                categoryId: 'cameras',
                dataType: 0,
                display: false,
                isSpecification: true,
                name: 'gtin',
                order: 0,
                required: true,
            },
        ]),
};

const ProductServiceMock = {
    listValidatedRangeProducts: (categoryId: string) =>
        of([
            {
                gtin: 0,
            },
            {
                gtin: 1,
            },
        ]),
};

let spectator: Spectator<SpecificationsSaveComponent>;
const createComponent = createComponentFactory({
    component: SpecificationsSaveComponent,
    imports: [],
    providers: [
        mockProvider(FieldService, FieldServiceMock),
        mockProvider(ProductService, ProductServiceMock)
    ],
});

let spectator: Spectator<SpecificationsSaveComponent>;
const createComponent = createComponentFactory({
    component: SpecificationsSaveComponent
});

beforeEach(() => {
    spectator = createComponent();
    spectator.get(FieldService).list.andReturn(of([
        {
            id: 0,
            canCopy: false,
            categoryId: 'cameras',
            dataType: 0,
            display: false,
            isSpecification: true,
            name: 'gtin',
            order: 0,
            required: true,
        },
    ]));
    spectator.get(ProductService).listValidatedRangeProducts.andReturn(of([
        {
            gtin: 0,
        },
        {
            gtin: 1,
        },
    ]));
});

问题是,我有另一项服务不像其他两项那样工作。服务如下所示:

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

import { Category } from '@models';

@Injectable({
    providedIn: 'root',
})
export class SelectorService {
    private currentCategoriesSubject: BehaviorSubject<Category[]>;
    private currentCategorySubject: BehaviorSubject<string>;

    public categories: Observable<Category[]>;
    public category: Observable<string>;

    constructor() {
        this.currentCategoriesSubject = new BehaviorSubject<Category[]>(null);
        this.categories = this.currentCategoriesSubject.asObservable();

        this.currentCategorySubject = new BehaviorSubject<string>(null);
        this.category = this.currentCategorySubject.asObservable();
    }

    public setCategories(categories: Category[]): void {
        if (!categories.length) return;
        this.setCategory(categories[0].id);
        this.currentCategoriesSubject.next(categories);
    }

    public setCategory(categoryId: string): void {
        this.currentCategorySubject.next(categoryId);
    }

    public get currentCategory(): string {
        return this.currentCategorySubject.value;
    }

    public add(category: Category) {
        let categories = this.currentCategoriesSubject.value;
        if (!categories) categories = [];

        categories.push(category);

        this.currentCategoriesSubject.next(categories);
        this.currentCategorySubject.next(category.id);
    }

    public remove(categoryId: string) {
        let categories = this.currentCategoriesSubject.value;
        for (var i = 0; i < categories.length; i++) {
            if (categories[i].id === categoryId) {
                categories.splice(i, 1);
            }
        }

        this.currentCategoriesSubject.next(categories);

        if (!categories.length) return;

        this.currentCategorySubject.next(categories[0].id);
    }
}

我需要模拟的部分是公共属性category。 我不知道如何去嘲笑它。有人知道吗?

这是我正在测试的组件的 ngOnInit 方法:

ngOnInit() {
    console.log(this.selectorService);

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

【问题讨论】:

    标签: angular angular-spectator


    【解决方案1】:

    我可以通过使用第一个选项来解决这个问题:

    import { Spectator, createComponentFactory, mockProvider } from '@ngneat/spectator';
    import { HttpClientTestingModule } from '@angular/common/http/testing';
    import { ReactiveFormsModule } from '@angular/forms';
    import { of } from 'rxjs';
    
    import { ToastrModule } from 'ngx-toastr';
    import { SharedModule } from '@shared';
    import { SelectorService, ProductModelService } from '@core';
    import { FieldService, ProductService } from '@services';
    import { SpecificationsSaveComponent } from './specifications-save.component';
    
    describe('SpecificationsSaveComponent', () => {
        const SelectorServiceMock = {
            category: of('cameras'),
        };
    
        const FieldServiceMock = {
            list: (categoryId: string, specificationOnly: boolean) =>
                of([
                    {
                        id: 0,
                        canCopy: false,
                        categoryId: 'cameras',
                        dataType: 0,
                        display: false,
                        isSpecification: true,
                        name: 'gtin',
                        order: 0,
                        required: true,
                    },
                ]),
        };
    
        const ProductServiceMock = {
            listValidatedRangeProducts: (categoryId: string) =>
                of([
                    {
                        gtin: 0,
                    },
                    {
                        gtin: 1,
                    },
                ]),
        };
    
        let spectator: Spectator<SpecificationsSaveComponent>;
        const createComponent = createComponentFactory({
            component: SpecificationsSaveComponent,
            imports: [ReactiveFormsModule, HttpClientTestingModule, SharedModule, ToastrModule.forRoot()],
            providers: [
                mockProvider(SelectorService, SelectorServiceMock),
                mockProvider(FieldService, FieldServiceMock),
                mockProvider(ProductService, ProductServiceMock),
            ],
        });
    
        beforeEach(() => {
            spectator = createComponent();
        });
    
        it('should create', () => {
            expect(spectator.component).toBeTruthy();
        });
    });
    

    我不知道为什么第二个选项不起作用。 我可以看到选择器服务具有正确的值,但由于某种原因,它没有被传递给 ngOnInit 方法。 有人可以解释为什么这两行不起作用吗?

    beforeEach(() => {
        spectator = createComponent();
        spectator.get(SelectorService).category = of('cameras');
    });
    

    【讨论】:

      猜你喜欢
      • 2020-04-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      • 1970-01-01
      • 2014-12-07
      • 2019-03-05
      • 1970-01-01
      相关资源
      最近更新 更多