E2E 模拟 $httpBackend 对我来说实际上并没有通过 [英] E2E mock $httpBackend doesn't actually passThrough for me

查看:15
本文介绍了E2E 模拟 $httpBackend 对我来说实际上并没有通过的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然我相信我正在遵循 此处的说明来设置 $httpBackend 以将选定的请求传递给服务器,它不适合我.

Although I believe I'm following the instructions here for setting up $httpBackend to pass selected requests to the server, it's not working for me.

这是一个测试失败的 Plunkr,它显示了我在做什么并在评论似乎出了什么问题.

Here is a Plunkr with a failing test that shows what I'm doing and explains in comments what seems to be going wrong.

我的探索表明,出于某种原因,模拟 $httpBackend 没有真实 $httpBackend 的内部副本,因此,当需要通过 XHR 请求,它将它传递给模拟 $httpBackend 代替.第二次调用会引发异常,因为它不知道如何处理请求.

My spelunking suggests that, for some reason, the mock $httpBackend doesn't have an inner copy of the real $httpBackend so that, when it comes time to pass through the XHR request, it passes it to the mock $httpBackend instead. That second call throws an exception because it doesn't know what to do with the request.

我感激地记得您关于中途测试的帖子.您确定了介于单元测试和 E2E 测试之间的重要集成测试范围.我站在那个中间地带.

I remember with appreciation your post on midway testing. You identify an important range of integration testing that falls between unit- and E2E-testing. I am standing on that middle ground.

我不认为你在刻薄.你的回答是完全合理的......或者如果它与API 参考/ngMockE2E/$httpBackend".我引用:

I don't think you are being snarky at all. Your answer is perfect reasonable ... or it would be reasonable if it weren't contradicted by the text of the "API reference / ngMockE2E / $httpBackend". I quote:

此实现可用于通过 when api 及其快捷方式(whenGETwhenPOST 等)以静态或动态响应进行响应可选地将请求传递给真正的 $httpBackend 以获取特定请求(例如,与某些远程 API 交互或从网络服务器获取模板)...

This implementation can be used to respond with static or dynamic responses via the when api and its shortcuts (whenGET, whenPOST, etc) and optionally pass through requests to the real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch templates from a webserver) ...

[I]在端到端的测试场景中或者在开发应用程序的场景中,将真正的后端 api 替换为 mock,通常需要某些类别的请求绕过模拟并发出真正的http请求 ....要使用此行为配置后端,请使用passThrough请求处理程序时而不是respond.[强调我的].

[I]n an end-to-end testing scenario or in a scenario when an application is being developed with the real backend api replaced with a mock, it is often desirable for certain category of requests to bypass the mock and issue a real http request .... To configure the backend with this behavior use the passThrough request handler of when instead of respond.[emphasis mine].

文档没有提及 Jasmine 环境中的 E2E $httpBackend 使用问题.我想不出理由来排除它.如果有这样的原因,他们应该清楚地说明.说真的,谁读过一个 mock 组件却没想到会在测试环境中使用它?

The documentation is silent on the matter of E2E $httpBackend usage within a Jasmine environment. I can't think of a reason to preclude it. If there is such a reason they should state it clearly. Seriously, who reads about a mock component and doesn't anticipate using it in a test environment?

将请求传递给真正的 $httpBackend 以获取特定请求,例如与某些远程 api 交互"正是我打算做的.除了该组件的非模拟版本之外,真正的 $httpBackend"可能意味着什么?

To "pass through requests to the real $httpBackend for specific requests, e.g. to interact with certain remote apis" is precisely what I intend to do. What could they possibly mean by "real $httpBackend" except the non-mock version of that component?

我不明白你的说法

ngMocksE2E 模块设计用于执行实际 Angular 应用程序的服务器"端.

The ngMocksE2E module is designed to be used on the "server" side of things where the actual angular application is executing.

服务器"一词在该页面上恰好出现了 3 次,没有一次暗示任何应用程序代码将在服务器"上执行.我不知道你所说的在服务器端"执行的实际角度应用程序"是什么意思.

The word "server" appears exactly 3 times on that page, not once suggesting that any application code would be executed on a "server". I don't know what you mean by the "actual angular application" executing on "the 'server' side of things."

文档非常清楚 E2E $httpBackend 不限于 E2E 测试.它也适用于在开发应用程序时将真正的后端 api 替换为 mock 的场景".

The documentation is perfectly clear that the E2E $httpBackend is not limited to E2E testing. It is also for "a scenario when an application is being developed with the real backend api replaced with a mock".

这距离我的场景只有半步之遥,在该场景中,应用程序正在使用真正的后端 api 进行测试."

That's just a half step away from my scenario in which an application is being tested with the real backend api."

在我的场景中,SUT 正在调用从服务器获取数据的组件.我的测试是为了验证这个依赖组件是否成功地向真正的后端发出此类请求,并将以预期的方式检索或保存数据.这是一个无法通过模拟后端行为来充分满足的集成测试.

In my scenarios, the SUT is calling upon a component which fetches data from a server. My tests exist to verify that this dependent component succeeds in making such requests of the real backend and will retrieve or save data in the expected manner. This is an integration test that cannot be adequately satisfied by mocking the behavior of the backend.

当然,我可以使用模拟 XHR 响应来测试(并进行测试)组件正确响应我预测后端行为的能力.这与验证组件是否对 actual 后端的行为做出适当响应不同......这可能会随着应用程序的发展而改变,并以某种重要的方式偏离模拟的响应.

Of course I can test (and do test) with mock XHR responses the component's ability to respond properly to what I predict will be the backend's behavior. That is not the same as validating that the component responds appropriately to the actual backend's behavior ... which might change as the application evolves and depart from the mocked responses in some significant way.

如果我了解如何将它交换到 SUT 的代码路径中,我会考虑为此目的使用您的中间测试器.我不.我认为您的 ngMidwayTester 无法访问发出 XHR 请求的组件.但我确实知道如何在必要时将真正的 XHR 助手加入管道.

I would consider using your midway tester for this purpose if I understood how to swap it into the SUT's code path. I don't. I think the component making XHR requests is inaccessible to your ngMidwayTester. But I do know how to jam a real XHR helper into the pipeline if I have to.

这就是我现在的立场.

有人可以展示如何让 $httpBackend 将某些请求传递到服务器 - 正如文档所宣称的那样 - 或者我将自己替换 passThrough 实现一个有效的 XHR 实现.

Either someone can show how to make $httpBackend pass certain requests through to the server - as the documentation proclaims it can - or I will replace the passThrough implementation myself with a working XHR implementation.

我更喜欢第一个选项.如果驱动到第二个,我将在此处提供指向它的链接,以帮助其他分享我的需求和我对 API 文档的解释的人.

I prefer the first option. If driven to the second, I shall offer a link to it here for the benefit of others who share my needs and my interpretation of the API documentation.

我错过了第三种方式吗?

Is there a 3rd way I'm missing?

推荐答案

下面是ngMockE2E模块中$httpBackend的用途说明.

The following is an explanation of the purpose of the $httpBackend that is in the ngMockE2E module.

ngMockE2E 模块根本不是设计或打算在 jasmine 规范中使用.

The ngMockE2E module is simply not designed nor intended to be used from within a jasmine specification.

在进行端到端测试时,测试有两个方面.一个是正​​在测试的 Angular 应用程序,另一个是 Jasmine 规范中的 angular-scenario 代码.

When doing end-to-end testing there are two sides to the test. One is the angular application that is being tested, the other is the angular-scenario code that lives in the Jasmine Specification.

在 E2E 测试中,没有 angular 模块、ng-mocks 或任何与 jasmine 方面相关的东西(除了场景运行器).

Under E2E tests there are no angular module, or ng-mocks, or anything angular-related on the jasmine side of things (other than the scenario runner).

ngMocksE2E 模块设计用于执行实际 Angular 应用程序的服务器"端.它的主要目的是使我们能够预先响应,以便集成级别的 UI 测试可以比每个页面实际到服务器获取 JSON 更快地进行.

The ngMocksE2E module is designed to be used on the "server" side of things where the actual angular application is executing. It's main purpose is to enable us to pre-can responses so that integration-level UI testing can proceed much quicker than if each page actually went to the server for JSON.

当将 jasmine 与 ng-mocks 一起使用时,angular 将始终将 $httpBackend 替换为 mock 后端.添加 ngMocksE2E 模块时,它将无法获取任何真实" $httpBackend 并且正如您已经发现的那样,只会包装模拟并委托给它在传递中.

When using jasmine along with ng-mocks, angular will always replace the $httpBackend with the mock backend. When adding the ngMocksE2E module it will not be able to get ahold of any "real" $httpBackend and as you have already found out, will just wrap the mock and delegate to it on the pass-through.

您尝试编写的测试似乎不是测试 UI 集成,而是测试应用程序 javascript 和服务器集成.

It would seem that the kind of test you are trying to write is a test that doesn't test the UI integration, but tests the application javascript and server integration.

这是完全合法的测试风格(在 Angular 社区中被称为midwayTesting").你的问题是你使用了错误的工具.

This is perfectly legitimate style of testing (referred to some as 'midwayTesting' in the angular community). Your problem is you are using the wrong tool.

我会看看这个:

https://github.com/yearofmoo/ngMidwayTester

您将使用它来代替 angular-mocks 和 angular.module() 以促进我假设您想要进行的那种测试.

Which you would use instead of angular-mocks and angular.module() in order to facilitate the kind of testing I'm assuming you want to do.

您可以在此处阅读更多信息:

You can read more about it here:

http://www.yearofmoo.com/2013/01/full-spectrum-testing-with-angularjs-and-karma.html

(抱歉,如果您已经链接到那里)

(apologies if you have already been linked there)

(解决有问题的其他评论)

(To address additional comments in question)

您真的很生气,因为文档不清楚 ngMockE2E 不能在端到端测试设置的客户端(即 karma/jasmine)端使用.像你解释的那样去解释并没有不合理,但这并不能改变解释是错误的事实.

You have a real beef in that the documentation is not clear that ngMockE2E cannot be used on the client (i.e. karma/jasmine) side of an end-to-end testing setup. It is not unreasonable to interpret things like you have interpreted them, but it doesn't change the fact that the interpretation is wrong.

如果在应用程序的服务器端而不是客户端使用时,ngMockE2E 将通过请求.这意味着您仍然可以通过某些难以模拟为预设响应的请求.我所说的客户端和服务器端的意思是在端到端测试中有两个端点.您拥有由标准应用服务器提供服务的要测试的应用程序,并且您拥有驱动应用程序的测试代码,该代码通常在 Karma 或另一个测试运行程序中执行,它使用标准 HTTP 请求与正在执行的应用程序进行通信另一个过程.

The ngMockE2E will pass through requests if instructed when used on the server side of an application rather than on the client side. This is meant so that you can still pass through certain requests that are hard to mock as pre-canned responses. What I mean by client and server-side is that in end-to-end testing there are two ends. You have the application to be tested which is served by a standard application server, and you have the test code that is driving the application usually executing in Karma or another test runner, which uses standard HTTP requests to communicate to the application which is executing in another process.

如果您查看文档以及如何设置 ngMockE2E,您会注意到没有提及 Jasmine,并且说明是关于如何在真正的 Angular 应用程序中进行设置:

If you look at the documentation and how to setup ngMockE2E you will notice there is no mention of Jasmine, and the instructions are for how to set up in a real angular application:

myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
myAppDev.run(function($httpBackend) {
  phones = [{name: 'phone1'}, {name: 'phone2'}];

  // returns the current list of phones
  $httpBackend.whenGET('/phones').respond(phones);

  // adds a new phone to the phones array
  $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
    phones.push(angular.fromJson(data));
  });
  $httpBackend.whenGET(/^/templates//).passThrough();
  //...
});

正如您在此示例中所见,它们正在模拟所有 JSON 数据指令,同时让它仍然从服务器获取模板.

As you can see in this example, they are mocking all the JSON data instructions, while letting it still fetch the templates from the server.

为了从 jasmine 使用它,设置会完全不同,使用 angular.mock.module('ngMockE2E') 然后设置 $httpBackend.whenGET()beforeEach() 中,而不是在 module.run() 中.

In order to use it from jasmine the setup would be quite different, using angular.mock.module('ngMockE2E') and then setting up the $httpBackend.whenGET() in a beforeEach() rather than in a module.run().

就我链接到的 ngMidwayTester 而言,我相信这实际上与 ngMockE2E 兼容.本质上 ngMidwayTester 用它自己的实现替换了 angular.mock.module()inject().所以你可以这样使用它:

As far as ngMidwayTester I linked you to, I believe this would, in fact, be compatible with ngMockE2E. Essentially ngMidwayTester replaces angular.mock.module() and inject() with it's own implementations. So you could use it like this:

beforeEach(function(){
  tester = ngMidwayTester('app', 'ngMockE2E');
  $http = tester.inject('$http');
  $httpBackend = tester.inject('$httpBackend');
  $rootScope = tester.inject('$rootScope');
});

这应该可行,因为您不再使用 ngMock 模块(当您使用 angular.mock.module() 时总是包含该模块).使用 ngMidwayTester 时,事情应该完全按照您希望的方式工作.

This should work, because you are no longer using the ngMock module (which always gets included when you use angular.mock.module()). Things should work exactly like you want them to using ngMidwayTester.

这篇关于E2E 模拟 $httpBackend 对我来说实际上并没有通过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆