【问题标题】:Mock Angular HttpClient in protractor e2e test在量角器 e2e 测试中模拟 Angular HttpClient
【发布时间】:2021-04-26 04:06:04
【问题描述】:

我的应用程序在页面加载时立即对我的后端进行 http 调用。我的 e2e 测试失败了,因为我的 ci 管道中没有运行后端。

我尝试在 http 调用上使用 rxjs catchError 管道运算符

我尝试将整个 http 调用包装在 try / except 块中

我仍然在开发控制台中显示错误(这导致 e2e 测试失败)

我想知道如何为量角器测试提供模拟 HttpClient

实际的Http调用

return this.http.get<any>( url ).subscribe(...)

this.http 是 Angular 的 HttpClient 的一个实例)

规格文件:

import { AppPage } from './app.po';
import { browser, logging } from 'protractor';

describe( 'workspace-project App', () => {
  let page: AppPage;

  beforeEach( () => {
    page = new AppPage();
  } );

  it( 'should display login page', () => {
    page.navigateTo();
    expect( page.getLoginTitleText() ).toEqual( 'Welcome to\nApp\nClick below to sign in with Google' );
  } );

  afterEach( async () => {
    // Assert that there are no errors emitted from the browser
    const logs = await browser.manage().logs().get( logging.Type.BROWSER );
    expect( logs ).not.toContain( jasmine.objectContaining( {
      level: logging.Level.SEVERE,
    } as logging.Entry ) );
  } );
} );

量角器的页面对象文件 (app.po)

import { browser, by, element } from 'protractor';

export class AppPage {
  public navigateTo() {
    return browser.get( browser.baseUrl ) as Promise<any>;
  }

  public getLoginTitleText() {
    return element( by.css( 'app-root app-login div.login-wrapper form.login section.title' ) )
      .getText() as Promise<string>;
  }
}

开发控制台中的错误:

【问题讨论】:

  • 更常用的方法是为您的 api 调用制作带有一些预定义响应的模拟后端服务器,并在此基础上实现您的测试。我相信有很多库支持这种实现。如果您仍想模拟 http 模块,则需要制作不同的配置/应用程序进行测试

标签: angular protractor e2e-testing


【解决方案1】:

我个人觉得有用的是使用proxy.conf.js 指向前端的资产,但路径被重写。

代码中有基于spec === 'user-1'的条件响应。

const PROXY_CONFIG = [
  {
    context: ['/api'],
    target: 'http://localhost:4200',
    secure: false,
    bypass: function (req) {
      let spec = '';
      try {
        const url = new URL(req.headers.referer);
        spec = url.searchParams.get('e2e-spec');
      } catch (e) {
        // nothing to do
      }

      if (req.method === 'GET' && req.path === '/api') {
        return '/e2e-api/index.json';
      }
      if (req.method === 'POST' && req.path === '/api/gql') {
        req.method = 'GET';
        if (spec === 'user-1') {
          return '/e2e-api/gql-user-simple.json';
        }
        return '/e2e-api/gql-empty.json';
      }
    },
    logLevel: 'debug',
  },
];

module.exports = PROXY_CONFIG;

为此,我们需要在angular.json 中添加e2e 配置:

            "e2e": {
              "fileReplacements": [
                {
                  "replace": "apps/ct-frontend/src/environments/environment.ts",
                  "with": "apps/ct-frontend/src/environments/environment.e2e.ts"
                }
              ],
              "assets": ["apps/ct-frontend/src/e2e-api"]
            }

这是一个带有实现的仓库:

您可以下载它并像这样运行 e2e 测试:

  • npm install
  • npm run e2e ct-frontend-e2e

检查它如何处理虚假响应。

【讨论】:

    【解决方案2】:

    我只是在回答有关模拟 Angular HTTPClient 的问题。假设你有 Angular 4 或更高版本,有一个用于模拟 httpclient 的内置测试模块,称为 HttpClientTestingModule,你可以从 Testbed 获得。

    import { AppPage } from './app.po';
    import { browser, logging } from 'protractor';
    //add these imports:
    import { TestBed } from '@angular/core/testing';
    import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
    
    describe( 'workspace-project App', () => {
      let page: AppPage;
      var httpMock: HttpTestingController;
    
      beforeEach( () => {
          TestBed.configureTestingModule({
          imports: [
          HttpClientTestingModule
          ]
        });
        page = new AppPage();
        httpMock = TestBed.get(HttpTestingController);
      } );
    
    //add async keyword to test
    //mock up the get request by recreating the URL
      it( 'should display login page', async () => {
        let urlPrefix = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port;
        let url = urlPrefix + 'infoo';
        let navigateTo_call = page.navigateTo();
        const request = httpMock.expectOne(url); 
        navigateTo_call.then(res => { 
       //do your checks here
       expect( page.getLoginTitleText() ).toEqual( 'Welcome to\nApp\nClick below to sign in with Google' );
      });
       request.flush("a mock response object");
        
      } );
    
      afterEach( async () => {
        // Assert that there are no errors emitted from the browser
        const logs = await browser.manage().logs().get( logging.Type.BROWSER );
        expect( logs ).not.toContain( jasmine.objectContaining( {
          level: logging.Level.SEVERE,
        } as logging.Entry ) );
      } );
    } );
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多