-
Notifications
You must be signed in to change notification settings - Fork 27.6k
ngMockE2E $httpBackend "passThrough()" doesn't work #1434
Comments
I too have this issue. As far as I can tell, the mocked $httpBackend keeps the "real" $httpBackend as a delegate but for some reason, this delegate is also a mocked $httpBackend, which does not expect the request resulting in this error. |
Anyone got any feedback on this issue? I can't believe how hard it is to write an actual integration test in Angular... ugh. |
I found that this worked for me when I was having that problem on my views folder. Maybe it's a start for you too.
(from here https://groups.google.com/forum/?fromgroups=#!topic/angular/ObdxCoCObYU) |
And duplicate here: #2512 |
I don't see where #2512 is actually a duplicate. There, the problem is failing to actually instantiate ngMockE2E for the httpbackend. Here, the problem is that the ngMockE2E delegates passThrough() requests to ngMock httpbackend (i.e. doesn't use a real http backend as the delegate) |
I am also having this issue. |
As a workaround, I modified angular-mocks.js and commented out the registration of $HttpBackendProvider in ngMock module. This way, the $httpBackend in ngMockE2E will use the actual $httpBackend in ng module when passThrough option is used. |
I am having this issue too. This issue is reported from a year ago and still there... |
I'm using version 1.2.9 If you are using this is my setup:
and a sample
I was having problems when including |
I also noticed this when trying to debug this issue. In a "real" browser, the ngMockE2E backend keeps the real $httpBackend around as its |
I some more digging, and this appears to be an artifact of the fact that the angular-mocks injector ( Loading If we manually inject ng's $httpBackend into ngMockE2E, it looks like the delegate gets set correctly... If I make the following change to angular-mocks.js, @@ -1761,7 +1761,9 @@ angular.module('ngMock', ['ng']).provider({
* Currently there is only one mock present in this module -
* the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock.
*/
-angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) {
+angular.module('ngMockE2E', ['ng']).service('$httpBackend', function(){
+ return angular.injector(['ng']).get('$httpBackend');
+}).config(['$provide', function($provide) {
$provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator);
}]); |
@schmod why would you like to load both ngMock and ngMockE2E? Those are meant to be used for different tests types (unit vs. e2e). Mixing them sounds odd... What is your use-case? |
I'm not trying to load both ngMock and ngMockE2E. However, if I'm running Jasmine, and using the window.inject = angular.mock.inject = function() {
...
modules.unshift('ngMock');
modules.unshift('ng'); There are a few rare cases when I actually might want to use |
@schmod ok, so what is your actual issue / reproduce scenario? |
I have a service in my application that loads/caches images (in IndexedDB as a When writing unit tests around this service, I would like to be able to have Karma serve up a "real" image for consumption by my service. For practical reasons, it's easier to just include a real image in my To use When doing this, I inadvertently end up instantiating both Reproduce senario (inside of Jasmine/Karma/Chrome): describe('passThrough', function(){
var $http, $httpBackend, $rootScope;
beforeEach(function(){
module('ngMockE2E');
inject(function(_$http_, _$httpBackend_, _$rootScope_){
$http = _$http_;
$httpBackend = _$httpBackend_;
$rootScope = _$rootScope_;
});
});
it('should do something', function(){
$httpBackend.whenGET(/.*image.jpg$/).passThrough();
$http.get('image.jpg');
$rootScope.$apply();
});
}); This throws the error:
Admittedly, this probably breaks the strict definition of what a "unit" test is, although there's also no good reason for this to be quite so broken... |
@mstaessen unit test mocks and e2e mocks were never meant to be used together and I would suspect that there are many other issues with using both together. Are you doing any actual assertions on the downloaded images? |
$httpBackend is the only thing in the E2E mock, and we haven't had any other issues running with this configuration. I don't see any good reason why the two shouldn't be able to stack on top of each other. (And, yes. We are doing assertions on the downloaded images. The service itself tries to determine the validity of the images that it downloads, which is why it's important that we should be able to send it real data during testing) |
Similar issue being raised here: |
(Updated my comment above to mention the actual error that my reproduce scenario throws.) |
I also have looked into this, because I have an On line 1165, it calls a When this delegate (it calls the Is this the expected behaviour? I don't understand why it calls the mocked |
As per schmod's experiences above, I tried commenting out line 1759: |
Any updates on this? I'm having the same issue |
I'm not using Karma but Jasmine test runner. However I had the same problem too. The $delegate is not the real $http service but the mock itself. Anyway, as schmod and ashclarke, I commented that line too and it worked. On the 1.2.18 the line is the 1742:
|
+1 It would be handy to use |
Okay there is a workaround, but you will not be available to have both at the same time (unit test is expecting some call, e2e is just responding a fake or passThrough). Here is how to inject the $httpBackend from e2e in unit test //be careful order is important
describe('inject e2e $httpBackend', function () {
it('here the injection', function() {
var $httpBackend;
//instantiate your modules
angular.mock.module('ngMockE2E', 'openstack.keystone.v2')
angular.mock.module(function ($provide) {
//retrieve the $httpBackend from module ng and override $delegate from ngMockE2E
angular.injector(['ng'])
.invoke(function($httpBackend) {
$provide.value('$delegate', $httpBackend);
});
//retrieve the $httpBackend from module ng and override $delegate from ngMockE2E
angular.injector(['ngMockE2E'])
.invoke(['$httpBackend', function(_$httpBackend_){
$httpBackend = _$httpBackend_;
}]);
$provide.value('$httpBackend', $httpBackend);
});
//and then it works
$httpBackend.when('POST', '/identity/tokens').passThrough();
});
}); |
subscribing |
+1 |
1 similar comment
+1 |
…is loaded Allow $httpBackend.passThrough() to work normally when ngMock is loaded concurrently with ngMockE2E, as is typically the case when writing tests with angular.mock.module() Fixes angular#1434
…is loaded Allow $httpBackend.passThrough() to work normally when ngMock is loaded concurrently with ngMockE2E, as is typically the case when writing tests with angular.mock.module() Fixes angular#1434
+1 |
+1 |
2 similar comments
+1 |
+1 |
Adding to the chorus, +1. Here is the scenario. We have an isolated unit suite using Karma, jasmine and bard. Everything is mocked, that's fine. We'd also like an integration suite that does full or partial end to end tests, still using karma and jasmine, but not bard. It will make some http calls, say to our own api, but mock other calls, say to amazon s3 put urls or to api's that require too much setup to execute. Finally I'll have a non destructive smoke test using protractor. This should be possible, and thanks to all who have worked some magic for workarounds. |
+1 |
1 similar comment
+1 |
+1 Trying to unit test a directive with templateUrl and running into this issue. |
+1 same issue here |
Error: [$injector:modulerr] Failed to instantiate module demoApp due to: |
On a positive note: one comment in case this helps others. 😄 I was trying to mock the backend while testing the frontend logic in the browser (no unit test). I had some issues and reading this issue it seemed to confirm to me Angular's ngMockE2E did not support this scenario yet. However, upon double checking for me using a wildcard angular.module("buyCoApp.services").run(mockRun);
mockRun.$inject = ["$httpBackend", "$http", "_"];
function mockRun($httpBackend, $http) {
$httpBackend.whenGET("api/test").respond(function(method, url, data) {
...
});
$httpBackend.whenGET(/.*/).passThrough();
} So for the |
+1 |
Any solutions to this? |
I've had a PR open for several months now. No clue what I need to do to get it reviewed or merged, but... it's there. |
I guess there is no strong argument for the necessity to have both I still think that unit tests should not interact with the server at all, but if enough people find this useful, I think the best way would be to leave Just my 2 cents... |
The problem is that angular-mocks loads It's not hard to understand why somebody might want to write an integration test with Jasmine. In my case, I want to test some functionality that loads and processes some very large files (which are sometimes binaries). I'd rather not have to mock these files by inlining them into my tests -- it's far cleaner to simply make a "real" HTTP request to fetch them when they're needed. |
I love to make service tests to assure the back-end services still behave as I expect. Too often the back-end guys changes something without telling me, which resulted in a tester standing next to me :) @gkalpak: Including the pass through functionality directly in |
@schmod, if you have already loaded |
+ 1 |
Here's a working example of using ngMockE2E with $httpBackEnd
|
Hi, I'm trying to set up some test that actually do hit the backend, but I can't get this to work:
$httpBackend.whenPOST(/./).passThrough()
$httpBackend.whenGET(/./).passThrough()
But I get the error: "POST /some/url No more request expected"
I am still able to use .whenGET().respond(), and it's variants, to mock the requests. Am I doing something wrong with passThrough()?
The text was updated successfully, but these errors were encountered: