【问题标题】:Test the Value of a Property that is Set in a Subscribe测试在订阅中设置的属性的值
【发布时间】:2020-09-27 05:07:45
【问题描述】:

我正在使用 Jasmine 测试一个 Angular 应用程序,我试图弄清楚如何测试在组件内的 Observable 上的 subscribe 调用中设置的属性的值。我在这里整理了一个示例组件来说明这一点。

@Component({
    selector: 'app-list',
    templateUrl: './list.component.html',
    styleUrls: ['./list.component.css']
})
export class ListComponent {
    public Result[] Items;


    constructor(private myService: MyService) {

this.formControl.valueChanges.pipe( switchMap(value => myService.getResults(value)) ).subscribe(results => this.Items = results); } }

在此示例中,对于我的测试,我将从内部调用 getResults(),并进行测试以确保填充了 Items。由于这不能保证立即发生,但subscribe 逻辑完全在组件内,我应该如何等待以确保在检查Items 的值时不会得到undefined

编辑:这是迄今为止我如何测试它的示例。请注意,我已经更新了上面代码中的注释如何表明 observable 是由于 FormControl 值更改而被订阅的,而不仅仅是按钮单击,因此下面的 detectChanges

it(‘should pull results’, () => {
    const componentFixture = TestBed.createComponent(ListComponent);
    const component = componentFixture.componentInstance;
    const myService = TestBed.inject(MyService);
    spyOn(myService, ‘getResults’).and.returnValue(of([myTestItems]));
    component.formControl.setValue(‘abcdefg’);
    componentFixture.detectChanges();
    expect(component.Items).toEqual([myTestItems]);
}

【问题讨论】:

    标签: angular rxjs jasmine


    【解决方案1】:

    你必须在你的测试中实现request方法,以获得结果和状态,重点是使用status来确保你的api工作正常,你也可以使用timeout来获得响应。

    const request = require('request');
    const endpoint = 'http://localhost:3000/city';
    
    //get
    it('should return 200 response code', function (done) {
        request.get(endpoint, function (error, response) {
            expect(response.statusCode).toEqual(200);
            done();
        });
    });
    //post
    it('should fail on POST', function (done) {
        request.post(endpoint, {json: true, body: {}}, function (error, response) {
            expect(response.statusCode).toEqual(404);
            done();
        });
    });
    

    【讨论】:

    • 嗯,我不太明白。在这种情况下,我不是专门测试组件方法吗? API方法可以单独测试。
    【解决方案2】:

    这取决于你如何嘲笑myService.getResults()。如果它返回一个of(<IResult[]>)(它应该是这样的IMO),订阅将同步运行,因此它会立即运行。

    it('should set items on click', () => {
      // click on the element and make sure pullResults() gets called.
      // here we will call it directly
      // Make sure you are mocking myService.getResults() to return an observable in the form 
      // of `of([...])`
      component.pullResults();
      // go ahead and make the assertion right away
      expect(component.Items).toEqual(myTestItems);
    });
    

    【讨论】:

    • 是的,我正在使用of,但是在将代码转移到问题时我过于简化了。该代码实际上是由 FormControl.valueChange 触发的,而不是按钮单击。我已经用这些信息更新了问题,并添加了一个示例测试来解决,也许它会让我的问题更清楚。
    • 你的测试对我来说看起来不错,它没有通过吗?
    • 不,我在component.Items 中未定义,因此无法与我的测试数据进行比较。
    • 我认为它永远不会进入您的subscribe。尝试在订阅中添加console.log 以确保它被打印出来。如果它没有进入订阅,我认为你正面临这个问题:stackoverflow.com/questions/51910630/…。答案显示了如何从 HTML 进行值更改。另外,请尝试将fixture.detectChanges 放在setValue 之前,因为createComponent 之后的第一个fixture.detectChanges()ngOnInit 运行的时间,也许您的ngOnInit 中有需要的绑定。
    猜你喜欢
    • 1970-01-01
    • 2018-12-13
    • 2014-06-25
    • 1970-01-01
    • 2016-11-09
    • 2017-10-03
    • 2023-03-31
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多