【问题标题】:Angular 2+ Unit testing a service that calls a service that calls an httpclient getAngular 2+单元测试调用httpclient get的服务的服务
【发布时间】:2017-12-21 11:37:02
【问题描述】:

我在网上找到了很多关于如何测试发出 API 请求的服务的示例,但对于以下服务:

  • 调用另一个服务,该服务发出一个 HTTP 请求并传递这个 回到原来的服务
  • 根据该请求发出 http 请求

我正在努力让它发挥作用。这是我的代码示例:

beforeEach((done) => {
    TestBed.configureTestingModule({
        imports: [
            RouterTestingModule,
            HttpClientTestingModule,
            JwtModule.forRoot({
                jwtOptionsProvider: {
                    provide: JWT_OPTIONS,
                    useFactory: jwtOptionsFactory,
                    deps: []
                }
            }),
        ],
        providers: [
            ConfigService,
            AuthenticationService,
            UserService,
            JobService
        ]
    });

    let injector = getTestBed();
    sut = injector.get(JobService);
    httpMock = injector.get(HttpTestingController);
});

describe('Appointment Management', () =>{
    it('should set an apointment', () => {
        expect(sut).toBeDefined();
        const dummyResponse = 'dsfsdf';

        sut
        .setAppointmentDate('temp', new Date(2017, 12, 31))
        .subscribe(result => {
            expect(result).toEqual(dummyResponse)
        })

        const req = httpMock.expectOne('http://localhost:32307/appointments');
        expect(req.request.method).toBe('POST');
        req.flush(dummyResponse);
    });
})

为了更清楚地了解这里发生了什么,jobservice 正在测试中。它有configService和userService的依赖。

用户服务有configService和认证服务的依赖。

路由器和jwt服务是认证服务和用户服务的依赖。

所有服务也依赖于 httpclient。

我得到的实际回应:

错误:超时 - 在 jasmine.DEFAULT_TIMEOUT_INTERVAL 指定的超时内未调用异步回调。

它甚至不应该打一个真正的电话,所以我不确定它为什么会超时。我也尝试过删除依赖项所做的调用,这导致了同样的错误,例如

const userRequest = httpMock.expectOne('http://localhost:32307/user');
userRequest.flush('temp');

【问题讨论】:

  • @mplungjan 我不是投反对票的人,但问题不包含正在测试的代码并且缺少stackoverflow.com/help/mcve
  • 我可以看到它更清晰的唯一方法是,如果我将整个内容包装在顶层描述中 - 我没有看到任何一点。但我从来没有能够得到一个问题这里没有被否决:D
  • 告诉 OP 和我们其他人投票反对的原因会很有用。
  • @Craig 请提供所有相关代码。您正在测试的服务。他们不在那里。否则问题无法获得高质量的答案。

标签: javascript angular unit-testing typescript


【解决方案1】:

当您进行单元测试时,您测试的是被测试服务的功能。您无需测试其依赖项的作用。

这意味着,您只需测试该服务是否正在调用另一个服务,并模拟返回。

由于 jobService 正在测试中,并调用配置和用户服务(根据您所写的我理解),您应该像这样测试您的功能:

US = injector.get(UserService);
CS = injector.get(ConfigService);

it('Testing a function called myFunc in your service ...', () => {
  spyOn(US, 'myUserServiceFunctionCalled')
    .and.returnValue(Observable.of('The mocked answer returned by this function'))
  spyOn(CS, 'myConfigServiceFunctionCalled')
    .and.returnValue(Observable.of('The mocked answer returned by this function'))

  sut.myFunc(); // .subscribe if it's an Observable, and put your expects in it
  expect(US.myUserServiceFunctionCalled).toHaveBeenCalled();
  expect(CS.myConfigServiceFunctionCalled).toHaveBeenCalled();
});

【讨论】:

  • 这看起来很像我需要的。我仍然遇到同样的错误,但感谢您让我走上正轨!
  • 没问题!如果您不再需要它们,请取消模拟您的 HTTP 调用,也许这可以解决您的问题!
  • (通过取消模拟,我的意思是删除)
  • 我已将其标记为非常有用,但对于遇到此问题的其他人,我通过在 beforeEach 中设置上面显示的间谍以返回一些存根响应来解决此问题。我仍在使用 flush 方法来模拟我在测试 http 响应下的服务,我通过给 beforeEach 一个“完成”回调来解决异步回调超时错误,我在设置所有间谍和注入器模拟后调用该回调。我猜设置测试平台会导致问题,因为提供的服务具有使用其依赖项 http 方法的构造函数,因此在我的测试之前它没有完成。
  • 谢谢,但要添加到此语句中,您应该只在每次测试中调用调用的函数时添加beforeEach 中的间谍!否则,这就是浪费时间和资源:当然,在一个小项目上没关系,但在一个巨大的项目中,这不是一个好习惯!
猜你喜欢
  • 2017-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-20
  • 1970-01-01
  • 2019-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多