繁体   English   中英

模拟在Angular 2中返回observable的服务调用?

[英]Mocking service calls that return observables in Angular 2?

我一直在尝试模拟一些在我的Angular应用程序中返回observable的服务调用,但我根本无法创建一个有效的observable,它将在我的代码中触发catch()map()等调用。 例如:

我的服务:

create(): Observable<any> {
    return this.http
    .post('/api/stuff', { id: 123 })
    .catch(this.handleError)
    .map(this.extractData);
}

我的规格:

let authHttpMock = mock(AuthHttp);
when(authHttpMock.post('/api/stuff', { id: 123 })).thenReturn(Observable.create(observer => {
  observer.error(new Error('500!'));
}));

const myService = new MyService(instance(authHttpMock));
myService.create({ id: 123 }).subscribe(
    result => {
    expect(result).toBeTruthy();
    }
);

覆盖率分析告诉我, handleError方法从未被执行过。 在成功观察的情况下,它也不会通过extractData方法。

那可观察到哪里去了? 我如何返回一个适当的可观察量来测试这样的调用?

在测试代​​码中的某个地方我相信你需要这个代码:

AuthHttp.post('/api/stuff', {id : 123 }).subscribe(data => {});

有两种方法可以实现这一目标。

首先,在您的服务方法中,使用以下内容:

create(id:number):Obserable<any> {
  let url:string = 'http://localhost:3000/api/stuff';
  let data:any = {
    id: id
  };

  return this.http.post(url, JSON.stringify(data))
    .map((res:Response) => res.json());
    .catch((error:any) => this.handleError(error))
}

第二种方法是,调用如下服务:

create(id:number):Obserable<any> {
  let url:string = 'http://localhost:3000/api/stuff';
  let data:any = {
    id: id
  };

  return this.http.post(url, JSON.stringify(data))
    .map((res:Response) => res.json());
  }

当您调用服务方法时,请使用以下命令:

this._service.create(123)
  .subscribe((res:any) => {
    //do whatever with success
  },
  (error:any) => {
    this.handleError(error)
  });

您可以在服务中调用用于提取数据的方法this.extractData() ,而不是res.json() ,但总体而言,结果相同。

希望这可以帮助 :)

您需要先创建mockData,以便服务可以使用它。下面有2个文件。 将您的组件和服务名称分别替换为COMPONENT_NAME和SERVICE_NAME。

规格文件ts

describe('WalletComponent', () => {
  let component: WalletManagementComponent;
  let fixture: ComponentFixture<WalletManagementComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ReactiveFormsModule],
      declarations: [COMPONENT_NAME],
      schemas: [NO_ERRORS_SCHEMA],
      providers: [
        {provide: APP_BASE_HREF, useValue: '/'},
        {provide: SERVICE_NAME, useClass: serviceMockData}      
      ]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(COMPONENT_NAME);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('Should create WalletComponent', () => {
    expect(component).toBeTruthy();
  });

 });

您需要在根目录中创建名为testHelper(或任何名称)的目录

serviceMockData ts

import {Observable} from 'rxjs/Observable';

const result = {
  data: [
    {id: 0, name: 'Temp Data 1'},
    {id: 1, name: 'Temp Data 2'},
  ]
}; 

export class serviceMockData {
  constructor() {
  }

  getWalletAudits() {
    return Observable.of(result).map(res => res);
  }

}

如果您订阅错误处理程序怎么办? 例如在您的规范中:

const myService = new MyService(instance(authHttpMock));
myService.create({ id: 123 }).subscribe(
  result => {
    throw new Error('Not supposed to be here.')
  },
  err => expect(err).toBeDefined(),
);

(虽然我认为不应该这样)。

这就是我模拟失败的后端调用的方法:

// first, I provide mock http in TestBed.configure...
...
providers:
  {
    provide: Http,
    useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
    deps: [MockBackend, BaseRequestOptions]
  },
  ... // other providers, like your mockAuthHttp
]


// than in the test, I tell the mockBackend to fail.
// including other stuff here to, just to show a few more things that can be done

it('should handle errors if backend doesn\'t like us', async(() => {
  let service = TestBed.get(MyService);
  let mockBackend = TestBed.get(MockBackend);
  mockBackend.connections.subscribe((c: any) => {
    if (c.request.url.indexOf('/api/stuff') !== -1) {
      // you can check stuff here, like c.request.method or c.request._body
      const err: ResponseError = new ResponseError('Stuff not good.');
      err.status = 404;
      return c.mockError(err);
    }
    throw new Error('Wrong url called.');
  });

  myService.create('whatever').subscribe((r: any) => {
    throw new Error('Should not have been a success.');
  },
  (err: any) => {
    expect(err.message).toEqual('Stuff not good.');
  });
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM