I'm using Angular's HttpClientTestingModule
and HttpTestingController
for mocking HTTP requests. The login
method of my service AuthenticationService
does two things:
- Makes a
POST
request to the server. If the credentials are valid, the server returns aUser
object. - "Logs" in a user by saving the response in
localStorage
.
As a result, I want to have two tests for my login
method:
- Test if the user is returned
- Test if localStorage has been set
I can include both tests in a single it
block, but I don't want to do that. I want to have one assert per unit test.
If I split them into different tests (as shown in the example below), there is a lot of code repetition. Is there a better way to do this?
Here is the relevant section of the authentication.service.spec.ts
file.
...
let authenticationService: AuthenticationService;
let httpTestingController: HttpTestingController;
let store = {};
// Create a mock user object for testing purposes
const mockUser: User = {
name: 'name',
email: 'email@example.com',
}
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AuthenticationService],
});
authenticationService = TestBed.inject(AuthenticationService);
httpTestingController = TestBed.inject(HttpTestingController);
// Create mock localStorage
spyOn(localStorage, 'getItem').and.callFake(key => {
return store[key];
});
spyOn(localStorage, 'setItem').and.callFake((key, value) => {
return store[key] = value + '';
});
spyOn(localStorage, 'removeItem').and.callFake(key => {
delete store[key];
});
});
describe('login', () => {
it('should return user', () => {
authenticationService.login('name', 'email@example.com').subscribe(
data => {
expect(data).toEqual(mockUser);
}
)
const req = httpTestingController.expectOne('http://example.com/login');
expect(req.request.method).toEqual('POST');
req.flush(mockUser);
});
it('should set localstorage', () => {
authenticationService.login('name', 'email@example.com').subscribe(
data => {
expect(localStorage.getItem('theUser')).toEqual(JSON.stringify(mockUser));
}
)
const req = httpTestingController.expectOne('http://example.com/login');
expect(req.request.method).toEqual('POST');
req.flush(mockUser);
});
afterEach(() => {
httpTestingController.verify();
});
});
...