首页 > 解决方案 > 如何在茉莉花中测试 map() 响应 JSON

问题描述

在 jasmine 服务中测试 map() 响应 JSON 的最佳方法是什么。

在这段代码中,我可以从 ws 获取我所有的类型警报。现在我想测试这个服务。为此,我尝试了一些如下代码。

 public typegetall(): Observable<Alarm[]> {
        ...
    return this.http.get(Api.getUrl(Api.URLS.typegetall), {
      headers: headers
    })
      .map((response: Response) => {
        let res = response.json();
        if (res.StatusCode === 1) {
          this.auth.logout();
        } else {
          return res.StatusDescription.map(alarm => {
            return new Alarm(alarm);
          });
        }
      });
  }

我试过这个单元测试:

    describe(`Service`, () => {
         beforeEach(() => {
            TestBed.configureTestingModule({
                declarations: [AlarmsTableComponent],
                imports: [],
                providers: [
                    { provide: AlarmsService]
            }).compileComponents()
                .then(() => {
                    myComponent = TestBed.createComponent(AlarmsTableComponent).componentInstance;
                    myService = TestBed.get(AlarmsService);
                });
        });
               afterEach(inject([HttpTestingController], (backend: HttpTestingController) => {
              backend.verify();
        }));
             it('alarms get all', inject([AlarmsService], (alarmeservice: AlarmsService) => {
            expect(alarmeservice.typegetall());
        }));
});

你能问我一些想法来测试这个吗?

编辑:

it('should return reasonable json ssss', inject([AlarmsService, MockBackend], fakeAsync((service: AlarmsService, mockBackend) => {

    const mockResponse = {
        data: [
            { alarmnumber: 0, alarmdesc: 'All cats are lions' },
            { alarmnumber: 1, alarmdesc: 'Video 1' },
            { alarmnumber: 2, alarmdesc: 'Video 2' },
            { alarmnumber: 3, alarmdesc: 'Video 3' },
        ]
    };

    mockBackend.connections.subscribe(connection => {
        connection.mockRespond(new Response(
            new ResponseOptions({
                body: [
                    { alarmnumber: 0, alarmdesc: 'All cats are lions' },
                    { alarmnumber: 1, alarmdesc: 'Video 1' },
                    { alarmnumber: 2, alarmdesc: 'Video 2' },
                    { alarmnumber: 3, alarmdesc: 'Video 3' },
                ]
            })));
    });

    service.typegetall().subscribe(alarmstype => {
        console.log(alarmstype)
        expect(alarmstype.length).toBe(3);
        expect(alarmstype[0].alarmdesc).toEqual("All cats are lions");
    });

    tick();
})));

结果:错误:无法从伪造的异步测试中生成 XHR。请求网址:http://xxxxxx/v1/products

标签: angularunit-testingtypescriptjasmine

解决方案


我看到两个要测试的案例:when thestatusCode === 1和 when statusCode !== 1

对于第一个测试:模拟您的后端以将响应作为具有StatusCode属性的可观察对象返回,设置为 1。

logout您应该为对象中的方法创建一个 jasmine 间谍auth

然后,订阅typegetall()方法并检查此订阅是否logout已被调用。

对于第二个测试:模拟您的后端以将响应作为具有StatusCode属性的可观察对象返回,设置为 2 并且将StatusDescription属性设置为数组alarm,但尚未实例化为警报。

typegetall()然后,使用返回数据(您的警报数组)订阅。在此订阅中,您可以测试每个项目的长度以及它们是否是 Alarm 的实例。

查看官方测试文档以了解如何创建模拟响应。

为了第一 :

it('should call logout when statusCode is equal to 1', () => 
{
     alarmService = TestBed.get(AlarmService);
     authService = TestBed.get(AuthService);
    /* Put your mock response here, an observable of object with StatusCode set to 1 */
    spyOn(authService, 'logout');
    alarmService.typegetall().subscribe(() => {
        expect(authService.logout).toHaveBeenCalledTimes(1);
    });
}

对于第二个:

it('should return an array Alarm when statusCode is equal to 2', () => 
{
     alarmService = TestBed.get(AlarmService);
     authService = TestBed.get(AuthService);
    /* Put your mock response here, an observable of object with StatusCode set to 2 and StatusDescription set to an array of 3 alarm object*/
    spyOn(authService, 'logout');
    alarmService.typegetall().subscribe((alarms: Alarm[]) => {            
        expect(authService.logout).not.toHaveBeenCalled;
        expect(alarms.length).toBe(3);
        alarms.forEach(alarm => expect(jasmine.any(alarm instanceof Alarm)).toBeTruthy());
        /*
           Other expectations to check object properties values, such as :
           expect(alarms[0].aProperty).toBe(...);
        */
    });
}

catchError要测试错误,请在您的服务上添加 rxjs运算符(在此处了解更多信息):

public typegetall(): Observable<Alarm[]> {
    ...
return this.http.get(Api.getUrl(Api.URLS.typegetall), {
  headers: headers
})
  .map((response: Response) => {
    let res = response.json();
    if (res.StatusCode === 1) {
      this.auth.logout();
    } else {
      return res.StatusDescription.map(alarm => {
        return new Alarm(alarm);
      });
    }
  })
  .catchError(error => of(`An error occured: ${error}`));
}

并像这样测试它:

 it('should get an error', () => 
{
     alarmService = TestBed.get(AlarmService);
    /* Create your mock response error here, an observable created with '_throw' and return a value (ex: 'shit, error !') */
    alarmService.typegetall().subscribe(error => expect(error).toBe('shit, error !'));
}

推荐阅读