## Unit Testing Guidelines A unit tests has 3 goals that it should accomplish to test a javascript object: * Checks success, error, and edge cases * Tests as few objects as possible * Demonstrates how an object should be used
With those 3 goals in mind, its important to realize that the variety of AngularJS object types means that the same approach won’t work for each and every object. Since the OpenLMIS-UI coding conventions layout patterns for different types of AngularJS objects, it’s also possible to illustrate how to unit test objects that follow those conventions.
Check out [AngularJS’s unit testing guide](https://docs.angularjs.org/guide/unit-testing), its well written and many of out tests follow their styles.
Here are some general rules to keep in mind while writing any unit tests: * Keep beforeEach statements short and to the point, which will help other’s read your statements * Understand how to use [Spies in Jasmine,](https://jasmine.github.io/1.3/introduction.html#section-Spies) they can help isolate objects and provide test cases
### Defining variables
The version of Jasmine we’re using discourages using the define-block scoped variables as they might be causing memory leaks. In order to prevent that, it is suggested to use ‘this’ as a way of sharing variables between beforeEach, afterEach, inject and it blocks. Keep in mind that closures inside those block will have a different context and thus ‘this’ will refer to a different object. Below are two examples on how to and how to not write unit tests for OpenLMIS.
#### Do
```Javascript describe(‘CustomResource’, function() {
- beforeEach(function() {
module(‘custom’);
- inject(function($injector) {
this.subjectUnderTest = $injector.get(‘subjectUnderTest’); this.$rootScope = $injector.get(‘$rootScope’);
});
this.expected = ‘expectedString’;
});
describe(‘returnSomething’, function() {
- beforeEach(function() {
this.subjectUnderTest.prepareForTest();
});
- it(‘should return something’, function() {
var result; this.subjectUnderTest.returnSomething()
- .then(function(something) {
result = something; //this.subjectUnderTest won’t be available as we have a different context here
});
this.$rootScope.$apply();
expect(result).toEqual(this.expected)
});
});
- afterEach(function() {
this.subjectUnderTest.clearAfterTest();
});
});¶
#### Don’t
```Javascript describe(‘CustomResource’, function() {
var expected, subjectUnderTest, $rootScope;
- beforeEach(function() {
module(‘custom’);
- inject(function($injector) {
subjectUnderTest = $injector.get(‘subjectUnderTest’); $rootScope = $injector.get(‘$rootScope’);
});
expected = ‘expectedString’;
});
describe(‘returnSomething’, function() {
- beforeEach(function() {
subjectUnderTest.prepareForTest();
});
- it(‘should return something’, function() {
var result; subjectUnderTest.returnSomething()
- .then(function(something) {
result = something;
});
$rootScope.$apply();
expect(result).toEqual(expected)
});
});
- afterEach(function() {
this.subjectUnderTest.clearAfterTest();
});