3

在我看来,我有加载动画,直到我收到来自 API 的响应。

//Displayed before we've received API response
<p ng-if="vm.vehicles == null">Loading ...</p>

//Displayed once we received response for the API
<table ng-if="vm.vehicles">
    <tr ng-repeat="vehicle.vm.vehicles">...</tr>

为了进行测试,我使用了$httpBackendAngular 模块。像这样的东西:

$httpBackend.whenGET('api/vehicles').respond({vehicles: [...]});

问题

我想写一个测试来检查加载动画是否显示。

我试过了:

expect(ptor.isElementPresent(By.cssContainingText('p', 'Loading'))).to.eventually.be.true;`

但我没有通过。所以我认为我需要有条件地延迟我从 $httpBackend 得到的响应。

我发现这篇博文http://endlessindirection.wordpress.com/2013/05/18/angularjs-delay-response-from-httpbackend/

但是,插入该配置方法使我的所有测试都失败了(我认为是因为模板没有及时加载),它会延迟所有响应,所以这并不是我真正需要的。

那么我怎样才能延迟那个电话的响应呢?理想情况下,我只想为该测试延迟它。

4

2 回答 2

0

我能够通过使用超时来解决 $httpBackend 的 response() 方法上可用的函数内的承诺,从而使其工作。

我正在我的 Angular 服务上测试一种方法,该方法使用 API 调用的结果填充列表。此外,我在该服务上有布尔值,指示列表何时加载以及何时完成。因此,在我的特定单元测试中,我只想确保“加载”布尔设置为 true,然后在完成时返回 false(并且“完成加载”布尔在成功填充该列表后设置为 true。

为此,我需要延迟我的模拟 httpBackend GET 响应,允许我检查“正在加载”布尔值是否设置为 true 并且“完成加载”布尔值未定义,但是在超时过去之后,两个布尔值都需要有新的价值观。

更新:很抱歉没有尽快更新。我之前在 response() 中放置了一个 $timeout,但是因为我没有执行 $timeout.flush(),所以 $timeout 函数中的期望语句没有执行。我不再以这种方式模拟延迟,但我忘记了我在这里发布了这个。感谢@Mark-Amery 引起我的注意。

var fakeList = [{ id: 1, name: "item 1" }, { id: 2, name: "item 2" }];

$http.expectGET('/myapi/myresource').respond(fakeList);

 myAngularService.myMethod();

 expect(myAngularService.listIsLoading).toBeTruthy();
 expect(myAngularService.listFinishedSuccessfully).toBeUndefined();

 $http.flush();

 expect(myAngularService.listIsLoading).toBeFalsy();
 expect(myAngularService.listFinishedSuccessfully).toBeTruthy();
 expect(myAngularService.myList).toEqual(fakeList);
于 2015-02-01T20:38:07.437 回答
0

$http尤其是的文档interceptors

这是有趣的一点:

response: 拦截器被 http 响应对象调用。该函数可以自由修改响应对象或创建一个新对象。该函数需要直接返回响应对象,或者作为promise包含响应的一个或一个新的响应对象。

换句话说,您可以拦截响应,而不是立即返回它,而是返回一个承诺,该承诺将在超时后返回响应......

例如plunkr 示例

但是在端到端测试的情况下,您必须处理一个$httpBackend对象。

这一点发挥作用:

与单元测试相反,在端到端测试场景中,或者在开发应用程序的场景中,将真正的后端 api 替换为模拟,通常需要某些类别的请求绕过模拟并发出一个真正的 http 请求(例如从网络服务器获取模板或静态文件)。要使用此行为配置后端,请使用 when 的 passThrough 请求处理程序而不是响应。

翻译:您可以使用.passThrough()并且您的拦截器应该可以工作:

$httpBackend.whenGET('api/vehicles').passThrough();

缺点是这会执行实际请求。

您还可以检查这个非常相似的问题: AngularJS - Using ngMockE2E $httpBackend how can I delay a specific response?

于 2014-09-28T23:36:39.407 回答