如何在量角器测试中在 httpBackendMocks 之间切换 [英] How to switch between httpBackendMocks in protractor test

查看:18
本文介绍了如何在量角器测试中在 httpBackendMocks 之间切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Protractor 测试中模拟对 API 调用的响应.在不同的测试中(以及在测试中),应用程序将 POST 到一个 API(总是相同的 URL),同时发布不同的数据,并期待不同的响应.

I am trying to mock responses to API calls within Protractor tests. In different tests (and within tests), the application will POST to an API (always the same URL) with different data POSTed, and expecting different responses.

具体来说,它是一个搜索引擎,我发送不同的查询并期望得到不同的结果.我让它像下面的代码一样成功运行,但它变得难以管理:

Specifically, it is a search engine, and I am sending different queries and expecting different results back. I have it working successfully like the code below, but it is getting unmanageable:

var httpBackendMock = function() {
  angular.module('httpBackendMock', ['ngMockE2E'])
    .run(function($httpBackend) {
      $httpBackend.whenPOST('//search_endpoint').respond(function(method, url, query, headers) {
        query = JSON.parse(query);
        if (query.bla = 'foo') {
          var results = {... lots of json ...};
        } else if (query.bla = 'bar') {
          var results = {... lots of json ...};
        } else if (query.something.else != 'whatever') {
          var results = {... lots of json ...};
        ... etc ...
        } else {
          var results = {... lots of json ...};
        }
        return [200, results];
      });
      $httpBackend.whenGET(/.*/).passThrough();
    })
};

beforeEach(function(){
  browser.addMockModule('httpBackendMock', httpBackendMock);
});

我想做的是将每个可能的响应放在一个单独的模拟中,然后删除 beforeEach 并在需要时添加模拟,如下所示:

What I'd like to do is have each possible response in a separate mock, then remove the beforeEach and add the mocks when needed, like so:

it('paginates', function(){
  // mocking a search with 13 results, showing 10 results per page
  browser.addMockModule('search_results', <some function>);
  $('#searchbox').sendKeys('some keyword search');
  $('#searchbutton').click();
  expect($('#results li').count()).toEqual(10);
  browser.clearMockModules();
  browser.addMockModule('search_results_page2', <some other function>);
  $('#next').click();
  expect($('#results li').count()).toEqual(3)
});

这有两个问题.

1) 它不起作用.清除并添加第二个模拟后,getRegisteredMockModules() 仅显示第二个模拟,但是根据 expect 和手册,似乎第一个模拟仍在使用中将 browser.pause() 与 ChromeDriver 一起使用时进行检查.看来你不能在不至少重新加载页面的情况下更改模拟.

1) It doesn't work. After clearing and adding the second mock, getRegisteredMockModules() shows only the second mock, however it seems like the first mock is still getting used, based on the expects and manual inspection when using browser.pause() with ChromeDriver. It seems that you can't change the mocks without at least reloading the page.

2) 即使它确实有效,但每个模拟模块都有大量重复代码,因为它必须设置所有内容,包括 passThrough().

2) Even if it did work, there is a huge amount of repeated code for each mock module, as it has to set up everything, including the passThrough().

如果我可以将我想要的响应传递到我正在添加的模拟中,那就更好了,但是我尝试了,并且传递给我自己的函数的任何内容在 angular.module 范围.我能想到的唯一方法是创建另一个带有提供者的角度模块,该提供者具有一个变量,可以跟踪所需的响应,并将其注入到模拟模块中.我还没有尝试过,但这似乎是一个不必要的复杂解决方案.

What would be even better would be if I could pass my desired response into the mock I am adding, however I tried that and anything passed into my own function isn't available within the angular.module scope. The only way I could think of to do that would be to create another angular module with a provider that had a single variable that would keep track of which response was desired, and inject that into the mocked module. I haven't tried that yet but it seems like an unnecessarily complex solution.

推荐答案

量角器中的模拟模块基本上是在每次整页刷新时在浏览器中执行的代码.这是一种为您省去自己做这件事的麻烦的机制,因为这样的刷新完全清除了浏览器的状态(当然 cookie 除外).正如您已经发现的那样,在您触发这样的刷新(使用 browser.get())之前,您的模块永远不会执行.如果需要,您可以使用 browser.executeScript() 手动执行此操作.

A mock-module in protractor is basically code that gets executed into the browser upon each full-page-refresh. It's a mechanism to save you the hassle of doing that yourself, since such a refresh cleans the state of the browser completely (with the exception of cookies of course). As you already found out, until you trigger such a refresh (with browser.get()), your modules are never executed. You can do that manually with browser.executeScript() if you want.

关于嘲笑你的后端所带来的混乱 - 我采取了以下方法:为您的后端提供一个默认的模拟实现,同时使其易于覆盖并在每次测试之前使用 init 函数进行注册:

Regarding the mess that ensues from mocking your back-end - I took the following approach: Have a default mock implementation for your back-end while making it easily overridable and registering it before each test with an init function:

mocked-backend-base.js

exports.httpBackendMockBase = function () {
    var exposeBackendCalls = function ($httpBackend) {
        this.getLoginAuthenticated = $httpBackend.whenGET(/login/authenticated.*/);
        this.getFindStuff = $httpBackend.whenGET(/lookup/findStuff.*/);
        this.getFullProfile = $httpBackend.whenGET(/api/full.*/);
    };

    angular.module('httpBackendMockBase', ['myClientApp', 'ngMockE2E'])
    .service('httpBackendMockBase', exposeBackendCalls)
    .run(function (httpBackendMockBase, testFixture) {
        httpBackendMockBase.getLoginAuthenticated.respond(function () {
            return [200, null, {}];
        });
        httpBackendMockBase.getFindStuff.respond(function () {
            return [200, { stuff: testFixture.stuff }, {}];
        });
        httpBackendMockBase.getFullProfile.respond(function () {
            return [200, { profile: testFixture.fullProfile }, {}];
        });
    });
};

如果您需要在某些时候覆盖它的一部分,请注册一个新的模拟模块.在你的 afterEach 块中删除它:

If you need parts of it overridden at some point register a new mock module. Remove it in your afterEach block:

mocked-backend-special-user.js

exports.httpBackendMock = function() {
    angular.module('httpBackendMockSpecialUser', []).run(function (httpBackendMockBase, testFixture) {
        httpBackendMockBase.getLoginAuthenticated.respond(function() {
            return [200, testFixture.specialUser, {}];
        });
    });
};

testFixture 来自另一个保存我们数据的模块,并在 mocked-backend-base 之前注册:

The testFixture is from another module that holds our data and is registered before the mocked-backend-base:

fixture.js

exports.data = {
    stuff: null,
    fullProfile: {},
    specialUser: {}
};

exports.module = function (data) {
    angular.module('backendFixture', []).constant('testFixture', data);
};

初始化函数:

var fixtureModule = require('fixture');
var baseMockedBackend = require('mocked-backend-base');

browser.addMockModule('backendFixture', fixtureModule.module, fixtureModule.data);
browser.addMockModule('httpBackendMockBase', baseMockedBackend.httpBackendMockBase);

这篇关于如何在量角器测试中在 httpBackendMocks 之间切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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