Let's take one of my file as an example, shall we ?
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();
});
});
Let me explain in details to you, step by step.
We start by describe
-ing our test. it allows us to group our tests. In this case, we group our tests by feature, and our feature is a service called ConfigurationService. We then provide a callback function : this is the function that will be ran by Jasmine to run your tests.
Next, we declare our variables. Here, we declare 2 variables, and one function : httpMock
, service
, and createFakeFile()
. Those variables will be helpful during the whole test group, so we declare them at the top level.
Then comes the beforeEach
: before every test, this function will be ran, to do something. In this one, it will create a TestBed : this is some boilerplate code that will create some kind of Angular module, to allow your tests to run as if your feature was in a real Angular application.
In this test bed, you need to declare your dependencies : since I'm testing an HTTP service, I have to import the HTTP testing module, and because my test uses routing, I also have to import the router testing module. I laso need to import the service being tested, and I import a SessionService
because I use it in my service too.
After that, I get the service instances of those dependencies through TestBed.get
: this will allow me to spy on their properties, and see their values and if they're called. This will also allow me to call the functions I want to test.
There comes the first tests. The first one is pretty simple and is implemented by default : I test if the service is getting created correctly. If not, it means you're lacking a dependency, or you mocked your dependencies wrong. The expect(service).toBeTruthy()
is the real test : with expect, jasmine expects (duh) the service to be truhty (i.e. it should not be equal to undefined or null).
The next test is a real test : during this test, I expect my function to call a certain endpoint, with a certain verb.
I start by saying that once the call has been made, I have to end the test. This is done by calling done
, which is the callback given just above.
Then, I mock an HTTP call : it means I make Angular believe I'm making an HTTP call, but I actually pretend to. But in its eyes, it's like making a real one : this is what a mock is : you simulate a behavior or a value. As you can see, I mock an HTTP call on a particular endpoint, and I expect a particular HTTP verb.
In the end, if my function getConfigurations
GETS on that URL, my test will succeed, and if not, it will fail. This means that if I ever change the endpoint in my actual service, the test will fail : this test prevents side effects.
The other tests are the same as that, so I don't need to explain them I guess.
If you wonder, I didn't do it alone, just like you i asked for help and followed tutorials. But once you get used to it, it becomes very fast and easy to test your features.
I hope this helps, and feel free to ask anything you want me to explain !