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.
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?
(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.)
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: '[email protected]'
};
}
};
/**
* 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 ... */
});
});
resetTestingModule
function into anafterEach
block in the top level describe. However, when I remove the duplicatebeforeEach
blocks from my nesteddescribe
s, my modified mock classMockRestService
, which is defined in the nesteddescribe
, does not get injected. Have I missed your point? – Venavenable