At, TechCompose Solutions, we have been following a practice of writing test cases for all front-end and back-end development.
This practice of writing test cases can help in
We use the Jest testing framework for Angular, NodeJS, and ReactJS.
Jest is currently the most popular JavaScript Testing Framework in the industry due to its simple syntax, minimum configuration & high speed, and extensive features such as easy mocking, code coverage, etc.
Click here to learn more about Jest.
This blog covers topics related to
Any additional modules used will be mentioned in the imports of the configureTestingModule method of the test cases as shown below.
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
}).compileComponents();
});
Any additional components used will be mentioned in the declaration of the configureTestingModule method of the test cases as shown below.
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent],
}).compileComponents();
});
Any additional services used, will be mentioned in the providers array of the configureTestingModule method of the test cases as shown below.
describe('AppComponent', () => {
beforeEach(waitForAsync () => {
TestBed.configureTestingModule({
providers: [{ provide: UserService, useValue: userServiceMock }],
declarations: [HomeComponent],
}).compileComponents();
});
});
Note: Here we’ve used useValue while providing a mock for the user-service. You can also use useClass.
Now I believe we have enough base so let’s dive straight into the Test cases 🚀:
Note: we’ve attached the Repository consisting code mentioned below for reference.
To write test cases related to local storage, the basic strategy would be to
It is because, by using our mocked localstorage, we can avoid disturbing actual localstorage while executing the code during test cases.
Let’s write a test case for the below function where
Here, We’re signing out a user by removing user data from local storage.
public onLogOut(): void {
this.userService.isUserLoggedIn.next(false);
localStorage.removeItem('user');
}
Now, first, we’ll mock the localstorage in the spec file as shown below
let setUpLocalStorageMock = () => {
localStorageMock = (function () {
let store: any = {};
return {
getItem(key: string) {
return store[key];
},
setItem(key: string, value: string) {
store[key] = value;
},
clear() {
store = {};
},
removeItem(key: string) {
delete store[key];
},
getAll() {
return store;
},
};
})();
// this is the place where we place our mocked localstorage instead of the real one.
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
localStorage.setItem('user', JSON.stringify(userData));
};
Note: In the last line, We've also added a fake userData for the actual function to remove.
Now, you can just add the setUpLocalStorageMock function to your spec file and call it in beforeEach method.
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [HomeComponent],
providers: [{ provide: UserService, useValue: userServiceMock }],
}).compileComponents();
setUpLocalStorageMock();
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
And finally, we’re all set to write an actual test case for the function.
it('onLogOut function test.', () => {
/* just for the reference that the user data exist
initially before we remove it by onLogOut function.
*/
expect(localStorage.getItem('user')).not.toBeFalsy();
//actual test case starts here.
component.onLogOut();
expect(userServiceMock.isUserLoggedIn.value).toBeFalsy();
expect(localStorage.getItem('user')).toBeFalsy();
});
This particular test case is related to the Behavior subject and the GET method to access the value of the Behavior subject.
Following is the example of the service file that has
export class UserService {
public usersArray: BehaviorSubject<any> = new BehaviorSubject([]);
public isUserLoggedIn: BehaviorSubject<any> = new BehaviorSubject(false);
public userData: BehaviorSubject<any> = new BehaviorSubject(undefined);
constructor() {}
public get userLoginValue(): boolean {
return this.isUserLoggedIn.value;
}
}
Here’s how we’ll write a test case for the userLoginValue with the GET method.
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('Check userLoginValue', () => {
/* here we're changing the default of
isUserLoggedIn behavior subject i.e false to true.
*/
service.isUserLoggedIn.next(true);
// here's where we access the value of the isUserLoggedIn behavior subject.
let loginValue = service.userLoginValue;
expect(loginValue).toBeTruthy();
});
});
Now, let’s see how we can write a test case for the component, using the userLoginValue with the GET method.
Below is the code snippet of the component accessing it,
ngOnInit(): void {
/* here's where value of isUserLoggedIn behavior
subject is accessed via userLoginValue */
this.isUserLoggedIn = this.userService.userLoginValue;
this.userService.usersArray.subscribe((usersList: any[]) => {
this.users = usersList;
});
}
We’ve to mock user service first for writing test cases for the component so that, no variables or functions of the actual service will be used & the testing for the component could be performed in isolation.
userServiceMock = {
isUserLoggedIn: new BehaviorSubject(false),
userLoginValue: {},
userData: new BehaviorSubject(undefined),
usersArray: new BehaviorSubject([]),
};
// attaching GET method to the userLoginValue function.
Object.defineProperty(userServiceMock, 'userLoginValue', {
get: () => {
return userServiceMock.isUserLoggedIn.value;
},
});
And so here’s how we can write a test case for calling the component function.
it('Test isUserLoggedIn behavior subject & userLoginValue get method.', () => {
// assigning true to the value instead of it's default value false.
userServiceMock.isUserLoggedIn.next(true);
component.ngOnInit();
// storing value in variable to test
const userLoginValue: boolean = userServiceMock.userLoginValue;
/* testing the value of variable
Note: storing userLoginValue value in variable & write
expect is not needed for actual code coverage it's just for reference */
expect(userLoginValue).toBeTruthy();
// testing the actual component variable using the value of userLoginValue
expect(component.isUserLoggedIn).toBeTruthy();
});
Copyright © 2024 TechCompose Solutions Pvt. Ltd. All rights reserved.