fakeAsync不等待异步操作完成

问题描述 投票:5回答:1

上下文

我正在测试使用基于可观察的服务的组件以获取一些数据并出于i18n目的显示它。

i18n服务是由于特定需要而定制的。

该组件在开发人员模式下工作(在某些模板中使用,工作正常),但测试失败。

来源

组件

@Component({
    selector     : "i18n",
    template     : '<span [innerHTML]="text"></span><span #wrapper hidden="true"><ng-content></ng-content><span>',
    encapsulation: ViewEncapsulation.None
})
export class I18nComponent implements OnChanges {

    constructor(private i18n:I18n) {
    }

    @ViewChild('wrapper')
    content:ElementRef;

    @Input('key')
    key:string;

    @Input('domain')
    domain:string;

    @Input('variables')
    variables:Variables = [];

    @Input("plural")
    plural:number;

    text:string;

    ngOnChanges():any {
        this.i18n.get(this.key, this.content.nativeElement.innerHTML, this.variables, this.domain).subscribe((res) => {
            this.text = res;
        });
    }
}

I18n.get

public get(key:string,
               defaultValue?:string,
               variables:Variables = {},
               domain?:string):Observable<string>{
    const catalog = {
                         "StackOverflowDomain":
                         {
                             "my-key":"my-value"
                         }
                    };

    return Observable.of(catalog[domain][key]).delay(300);
}

带有Variables

export interface Variables {
    [key:string]:any;
}

测试

describe("I18n component", () => {

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers   : [
                I18n,
                {
                    provide : I18N_CONFIG,
                    useValue: {
                        defaultLocale : "fr_FR",
                        variable_start: '~',
                        variable_end  : '~'
                    }
                },
                {
                    provide : I18N_LOADERS,
                    useClass: MockLocaleLoader,
                    multi   : true
                }
            ],
            declarations: [
                I18nComponent
            ]
        });
        fixture = TestBed.createComponent<I18nComponent>(I18nComponent);
        comp = fixture.componentInstance;
    });

    fit("can call I18n.get.", fakeAsync(() => {
        comp.content.nativeElement.innerHTML = "nope";
        comp.key = "test";
        comp.domain = "test domain";
        comp.ngOnChanges();
        tick();
        fixture.detectChanges();
        expect(comp.text).toBe("test value");
    }));

});

问题

测试失败并显示消息:

预计未定义为'测试值'。

错误:队列中还有1个定期计时器。

因为i18n.get在检查断言之前未完成工作,所以comp.text仍为undefined

已尝试

  • tick方法调用中添加了一个非常高的值,没有做任何更改(尝试使用5000)。
  • 使ngOnChanges返回在Promise<void>之后立即解析的this.text = res;,并使用在fakeAsyncdone中校准的then方法更改comp.ngOnChanges区域以进行简单测试。它可以工作,但是ngOnChanges不应返回Promise,我想要一个干净的解决方案。
angular typescript jasmine karma-jasmine
1个回答
3
投票

注意,async和fakeasync不像jasmine.done那样强大和包容。

[在撰写本文时,记下确切的注释:https://angular.io/guide/testing#component-fixture

它说:

编写完成的测试功能,但比异步和fakeAsync,是一种可行且偶尔必要的技术。对于例如,在测试代码时,您不能调用async或fakeAsync涉及到intervalTimer,这在测试异步时很常见Observable

© www.soinside.com 2019 - 2024. All rights reserved.