Angular2在ngOnInit错误中使用EventEmitter订阅测试模块

时间:2016-12-14 15:43:49

标签: angular testing jasmine eventemitter

我在为我创建的Angular2组件编写测试模块时遇到问题。有问题的组件在其中的ngOnInit方法中订阅了另一个服务的EventEmitter。然后,该组件将订阅此EventEmitter并侦听更改。以下是相关组件:

import { Component } from "@angular/core";
import { Product } from "../../../classes/Product";
import { ProductService } from "../../../services/product.service";
import { ConfigObject } from "../../../ConfigObject";
import { productHelper } from "../../../helpers/productHelper";


@Component({
    selector: 'product-component',
    templateUrl: '/app/views/catalog/products/product-dashboard.html',
    moduleId: module.id
})

export class ProductComponent {
    globals = ConfigObject;
    products: Product[] = [];
    productsLoaded = false;

    productPayload = {
        order           : 'asc',
        order_by        : 'title',
        category_id     : 0,
        resize          : true,
        imgHeight       : 200,
        imgWidth        : 200,
        active          : 1,
        searchTerm      : '',
        manufacturer    : null
    };

    constructor(
        private _productService: ProductService
    ) {

    }

    getProducts(filters) {
        this.productsLoaded = false;

        this._productService.getProducts(filters)
            .subscribe(
                products => { this.products = productHelper.processImagesAndDownloads(products)},
                ()       => { },
                ()       => { this.productsLoaded = true }
        );
    }

    ngOnInit() {
        this._productService.emitter.subscribe(
            (products) => {
                this.products = productHelper.processImagesAndDownloads(products);
            },
            ()       => { },
            ()       => { }
        );

        this.getProducts({});
    }

}

如您所见,使用ngOnInit方法订阅_productService.emitter EventEmitter。

我试图使用spyOn方法来模拟此事件发射器,但没有成功。我似乎无法正确地进行此组件测试。任何人都可以看到问题在这里:

import { ProductService } from "../../../../services/product.service";
import { TestBed, ComponentFixture, async } from "@angular/core/testing";
import { ProductComponent } from "../../../../components/catalog/products/ProductComponent";
import { HttpModule } from "@angular/http";
import { DebugElement, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";

let MockProductService = {
    emitter: () => {}
};

let comp:    ProductComponent;
let fixture: ComponentFixture<ProductComponent>;
let de:      DebugElement;
let el:      HTMLElement;

describe('Component: Product Component', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                ProductComponent
            ],
            providers: [
                {
                    provide: ProductService, useValue: MockProductService
                }
            ],
            imports: [
                HttpModule
            ],
            schemas: [CUSTOM_ELEMENTS_SCHEMA]
        });
    });

    it('Should check that products are loaded in the template', async(() => {

        TestBed.compileComponents()
            .then(() => {

                fixture = TestBed.createComponent(ProductComponent);
                comp = fixture.componentInstance;

                spyOn(MockProductService, 'emitter').and.returnValue({
                    subscribe: () => {}
                });
                comp.ngOnInit();

                expect(MockProductService.emitter).toHaveBeenCalled();
        });
    }));

});

我收到的错误是:

Failed: Uncaught (in promise): TypeError: this._productService.emitter.subscribe is not a function

1 个答案:

答案 0 :(得分:1)

emitter不会从组件中调用作为方法。它只作为属性访问

this._productService.emitter

因为它永远不会被称为方法,所以你的间谍是没用的。

您只需将emitter的值分配给Observable即可。这样,当组件订阅时,它实际上得到一个值

import 'rxjs/add/observable/of';

MockProductService.emitter = Observable.of(products);

// don't call ngOnitInit. Use detectChanges instead
fixture.detectChanges();

// wait for observable subscription to resolve
fixture.whenStable().then(() => {
  // do other stuff
  expect(comp.products).toBe(whatever)
})

您还需要在模拟上处理getProducts方法。

顺便说一下,EventEmitter并不真正意味着用于服务。为此,您应该使用Subject s。它们几乎完全相同,但仍然建议不要以这种方式使用EventEmitter。只需谷歌如何使用Subject。我确定那里有很多文章/帖子。