写angular2测试并更改模拟返回值 - 让它干? [英] Write angular2 tests and changing the mock return values - make it DRY?

查看:120
本文介绍了写angular2测试并更改模拟返回值 - 让它干?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为服务编写一些测试,我正在改变模拟函数的响应来测试各种情况。目前,每当我想要更改模拟的响应时,我需要重置TestBed并再次配置测试模块,将我的新Mocks作为依赖项注入。

I'm writing some tests for a service and I'm altering the response from mock functions to test various cases. At the moment, every time I want to change the response of a mock, I need to reset the TestBed and configure the testing module again, injecting my new Mocks as dependencies.

我觉得必须有一个DRYer方式来编写这个规范,但我无法弄明白。有没有人有任何想法?

I feel like there must be a DRYer way to write this spec, but I can't figure it out. Does anyone have any ideas?

(我知道我可以将此服务的测试编写为标准的ES6类,但我的组件和服务与我的组件和服务相同使用来自角度的Http响应模拟东西。)

(I understand that I could write tests for this service as a standard ES6 class, but I get the same scenario with my components and services that use the Http response mocking stuff from angular.)

这是我的spec文件:

Here is my spec file:

import { TestBed, inject } from '@angular/core/testing';
import { Observable } from 'rxjs/Observable';
import { UserService, RestService } from '../index';
import { User } from '../../../models/index';


let getUserSpy = jasmine.createSpy('getUser');
let upsertUserSpy = jasmine.createSpy('upsertUser');


// NOTE that initally, the MockRestService throws errors for all responses
class MockRestService {
  getUser = getUserSpy.and.returnValue(Observable.throw('no thanks'));
  upsertUser = upsertUserSpy.and.returnValue(Observable.throw('no thanks'));
}


describe('User service - ', () => {

  let service;

  /**
   * First TestBed configuration
   */
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        UserService,
        {
          provide: RestService,
          useClass: MockRestService,
        }
      ]
    });
  });

  beforeEach(inject([UserService], (user: UserService) => {
    service = user;
  }));

  /* ... tests ... */

  describe('getUser/ upsertUser succeeds with INVALID user - ', () => {

    /**
     * Altering mock
     */
    class MockRestService {
      getUser = getUserSpy.and.returnValue(Observable.of({json: () => {
        return {name: 'dave'};
      }}));
      upsertUser = upsertUserSpy.and.returnValue(Observable.of({json: () => {}}));
    }

    /**
     * Reset and reconfigure TestBed. Lots of repetition!
     */
    beforeEach(() => {
      TestBed.resetTestingModule();
    });

    beforeEach(() => {
      TestBed.configureTestingModule({
        providers: [
          UserService,
          {
            provide: RestService,
            useClass: MockRestService,
          }
        ]
      });
    });

    beforeEach(inject([UserService], (user: UserService) => {
      service = user;
    }));

    /* ... tests ... */

  });

  describe('getUser/upsertUser succeeds with valid user', () => {
    const validResponse = {
      json: () => {
        return {
          firstName: 'dave',
          lastName: 'jones',
          email: 'dave@gmail.com'
        };
      }
    };

    /**
     * Altering mock
     */
    class MockRestService {
      getUser = getUserSpy.and.returnValue(Observable.of(validResponse));
      upsertUser = upsertUserSpy.and.returnValue(Observable.of(validResponse));
    }

    /**
     * Reset and reconfigure testbed. Lots of repetition!
     */
    beforeEach(() => {
      TestBed.resetTestingModule();
    });

    beforeEach(() => {
      TestBed.configureTestingModule({
        providers: [
          UserService,
          {
            provide: RestService,
            useClass: MockRestService,
          }
        ]
      });
    });

    beforeEach(inject([UserService], (user: UserService) => {
      service = user;
    }));

    /* ... tests ... */

  });

});


推荐答案

这可能是

function setupUserTestbed() {
    beforeEach(() => {
      TestBed.configureTestingModule({...});
    });

    afterEach(() => {
      TestBed.resetTestingModule();
    });
 }

...
setupUserTestbed();
...
setupUserTestbed();

的目的是描述块(除此之外)对测试报告中的规范进行分组)是在* 之前安排,在* 之后以最有效的方式安排

But the purpose of describe blocks (besides grouping the specs in test report) is to arrange before* and after* blocks in a way they are most efficient.

如果顶级描述块有 beforeEach 块,您可以确定它会影响嵌套 describe 块中的规范。如果 describe 块是兄弟,则应将常见行为移至顶级 describe 。如果sibling describe 块没有顶级 describe ,则应该创建它。

If top-level describe block has beforeEach block, you can be sure that it affects the specs in nested describe blocks. If describe blocks are siblings, common behaviour should be moved to top-level describe. If there's no top-level describe for sibling describe blocks, it should be created.

在发布的代码顶级 describe('用户服务 - ',()=> {...})已经 beforeEach TestBed.configureTestingModule TestBed.resetTestingModule (它应该在 afterEach )和 inject 之后执行。没有必要在嵌套的 describe 块中复制它们。

In posted code top-level describe('User service - ', () => { ... }) already has beforeEach blocks with TestBed.configureTestingModule, TestBed.resetTestingModule (it should be performed in afterEach) and inject. There's no need to duplicate them in nested describe blocks.

MockRestService的配方 class与在规范之间交替的任何模拟相同。它应该是 / var 变量:

The recipe for MockRestService class is the same as for any mock that alternates between specs. It should be a let/var variable:

describe(...
  let MockRestService = class MockRestService { ... };

  beforeEach(() => { Testbed... });

  describe(...
    MockRestService = class MockRestService { ... };

    beforeEach(inject(...));

此模式可能有很多变化。类本身可能是常量,但 getUser upsertUser 属性可以替代:

There can be a lot of variations of this pattern. The class itself may be constant, but getUser and upsertUser properties may alternate:

let getUserSpy;
let upsertUserSpy;

class MockRestService {
  getUser = getUserSpy;
  ...
}

describe(...

  beforeEach(() => { Testbed... });

  beforeEach(() => {
    getUserSpy = jasmine.createSpy().and.returnValue(...);
    ...
  });

  describe(...
    beforeEach(() => {
      getUserSpy = jasmine.createSpy().and.returnValue(...);
      ...
    });

    beforeEach(inject(...));

这也解决了一个重要问题,因为间谍应该在每个规范中都是新鲜的,即在 beforeEach getUserSpy upsertUserSpy 可在 Testbed 配置后重新分配但在 inject 之前(这是 MockRestService 类可能已实例化的地方)。

This also solves an important issue, because spies should be fresh in each spec, i.e. be defined in beforeEach. getUserSpy and upsertUserSpy can be re-assigned after Testbed configuration but before inject (this is where MockRestService class is likely instantiated).

这篇关于写angular2测试并更改模拟返回值 - 让它干?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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