angular - 模拟对象如何在 Angular jasmine 单元测试中工作

标签 angular angular-httpclient

我正在学习单元测试和 Angular,所以我都是初学者。
我已经引用了一些关于 Angular 单元测试 http 的教程和文章。

我无法理解 httpMock 使用 HttpTestingController 做了什么。我们调用实际服务的函数,那为什么我们称它为模拟呢?
什么是底层流程?
请引用一些文章以获得更好的理解。

提前致谢。

编辑:
这是issue我坚持使用 httpMock 的地方。

最佳答案

让我们以我的一个文件为例,好吗?

import { SimpleConfiguration } from '../../../../../model/SimpleConfiguration';
import { SessionService } from '../../../session/session.service';
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { ConfigurationService } from './configuration.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

describe('ConfigurationService', () => {

  let httpMock: HttpTestingController;
  let service: ConfigurationService;

  const createFakeFile = (fileName: string = 'fileName'): File => {
    const blob = new Blob([''], { type: 'text/html' });
    blob['lastModifiedDate'] = '';
    blob['name'] = fileName;
    return <File>blob;
  };

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        HttpClientTestingModule
      ],
      providers: [ConfigurationService, SessionService]
    });

    httpMock = TestBed.get(HttpTestingController);
    service = TestBed.get(ConfigurationService);
  });

  it('should be created', done => {
    expect(service).toBeTruthy();
    done();
  });

  it('getConfigurations should GET on postes-sources/:postID/configuration', (done) => {
    service.getConfigurations(0).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations');
    expect(successRequest.request.method).toEqual('GET');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('uploadFile should POST on postes-sources/:postID/configuration', (done) => {
    service.uploadFile(0, createFakeFile(), new SimpleConfiguration()).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations');
    expect(successRequest.request.method).toEqual('POST');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('updateComment should POST on postes-sources/:postID/configurations/:confID', (done) => {
    service.updateConfiguration(0, 0, new SimpleConfiguration()).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/configurations/0');
    expect(successRequest.request.method).toEqual('POST');
    successRequest.flush(null);
    httpMock.verify();
  });

  it('getComponentInformations should GET on postes-sources/:postID/tranches/:trancheID/parametres', (done) => {
    service.getComponentInformations(0, 0).subscribe(res => done());
    const successRequest = httpMock.expectOne(service.URL + 'postes-sources/0/tranches/0/parametres');
    expect(successRequest.request.method).toEqual('GET');
    successRequest.flush(null);
    httpMock.verify();
  });
});

让我一步一步地向你详细解释。
  • 我们从 describe 开始- 进行我们的测试。它允许我们对测试进行分组。在这种情况下,我们按功能对测试进行分组,我们的功能是一个名为 的服务。配置服务 .然后我们提供一个回调函数:这是由 Jasmine 运行以运行您的测试的函数。
  • 接下来,我们声明我们的变量。在这里,我们声明了 2 个变量和 1 个函数:httpMock , service , 和 createFakeFile() .这些变量在整个测试组中都会有帮助,所以我们在顶层声明它们。
  • 然后是 beforeEach : 每次测试前,都会运行这个函数,做点什么。在这个中,它将创建一个 试验台 :这是一些样板代码,它将创建某种 Angular 模块,以允许您的测试像在真正的 Angular 应用程序中一样运行。

  • 在此测试台中,您需要声明您的 依赖 : 因为我在测试一个HTTP服务,所以我必须导入HTTP测试模块,因为我的测试使用路由,所以我还必须导入路由器测试模块。我也需要导入正在测试的服务,我导入了 SessionService因为我也在我的服务中使用它。

    之后,我获取服务实例这些依赖项中的 TestBed.get :这将允许我监视它们的属性,并查看它们的值以及它们是否被调用。这也将允许我调用我想要测试的函数。
  • 这是第一个测试。第一个非常简单,默认实现:我测试是否正确创建了服务。如果不是,则意味着您缺少依赖项,或者您错误地模拟了您的依赖项。 expect(service).toBeTruthy()是真正的测试:有期待, Jasmine 期待 (呃)服务要真实 (即它不应该等于 undefined 或 null)。
  • 下一个测试是一个真正的测试:在这个测试中,我希望我的函数调用某个端点,带有某个动词。

  • 我首先说,一旦打了电话,我就必须结束测试。这是通过调用 done 来完成的。 ,这是上面给出的回调。

    然后,我模拟 HTTP 调用:这意味着我让 Angular 相信我在进行 HTTP 调用,但我实际上是假装的。但在它看来,这就像制作一个真实的:这就是模拟:你模拟一个行为或一个值 .如您所见,我在特定端点上模拟了一个 HTTP 调用,并且我期望一个特定的 HTTP 动词。

    最后,如果我的函数getConfigurations在那个 URL 上获取,我的测试将成功,如果没有,它将失败。这意味着如果我在实际服务中更改端点,测试将失败:此测试阻止 副作用 .

    其他测试与此相同,所以我想我不需要解释它们。

    如果您想知道,我不是一个人做的,就像您一样,我寻求帮助并遵循教程。但是一旦你习惯了它,测试你的功能就会变得非常快速和容易。

    我希望这会有所帮助,如果您希望我解释任何内容,请随时提出!

    关于angular - 模拟对象如何在 Angular jasmine 单元测试中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49942372/

    相关文章:

    angular - 在 Google App 脚本(Google 文档插件)中运行 Angular 7 时出错

    angular - Ionic 2 在应用程序启动后重定向到另一个页面

    angular - HttpInterceptor 处理 401 错误不返回 Observable

    angular - 有没有办法知道 rxjs websocket 是否打开

    angular - 在动态创建的组件angular 2中调用方法

    angular - 类型 'subscribe' 上不存在属性 'Promise<Client>'。 ngx-soap 包

    angular5 - Angular 5 通用 httpClient - 即使使用 HttpObserve 也无法获取实际的 http header 响应 :'response'

    angular - auth0 授权 api 调用返回 200 状态但仍然得到错误响应

    javascript - Angular:来自 observable 的法线数组