我正在为服务编写一些测试,并且我正在改变模拟函数的响应来测试各种情况。目前,每次我想要更改模拟的响应时,我都需要重置TestBed并再次配置测试模块,将我的新Mocks作为依赖项注入。
我觉得必须有一个DRYer方式来编写这个规范,但我无法弄明白。有没有人有任何想法?
(我知道我可以将此服务的测试编写为标准的ES6类,但是我的组件和服务使用Http响应模拟角度的东西得到了相同的场景。)
这是我的spec文件:
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 ... */
});
});
答案 0 :(得分:4)
可能是
的一些变种function setupUserTestbed() {
beforeEach(() => {
TestBed.configureTestingModule({...});
});
afterEach(() => {
TestBed.resetTestingModule();
});
}
...
setupUserTestbed();
...
setupUserTestbed();
但describe
阻止的目的(除了对测试报告中的规范进行分组)是以最有效的方式安排before*
和after*
块。
如果顶级describe
块有beforeEach
阻止,则可以确定它会影响嵌套describe
块中的规范。如果describe
块是兄弟姐妹,则应将常见行为移至顶级describe
。如果兄弟describe
块没有顶级describe
,则应该创建它。
在已发布的代码中,顶级describe('User service - ', () => { ... })
已beforeEach
块TestBed.configureTestingModule
,TestBed.resetTestingModule
(应在afterEach
中执行)和{{1} }}。没有必要在嵌套的inject
块中复制它们。
describe
类的配方与在规格之间交替的任何模拟相同。它应该是MockRestService
/ let
变量:
var
这种模式可能有很多变化。类本身可能是常量,但describe(...
let MockRestService = class MockRestService { ... };
beforeEach(() => { Testbed... });
describe(...
MockRestService = class MockRestService { ... };
beforeEach(inject(...));
和getUser
属性可以交替使用:
upsertUser
这也解决了一个重要的问题,因为间谍应该在每个规范中都是新鲜的,即在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
类的地方)。