If your wrap your unit tests in one global function, that function name must be unique across all of your tests
I have some OCD issues. I guess that’s why I like writing code. My OCD tendencies are no less apparent in my unit tests: I tend to wrap all of my tests in a global function.
The main reason for this is: test data.
Test data is a reality of unit tests and something that happens often. But I really hate to see a whole bunch of boilerplate code at the top of a unit test. I don’t want to see all of that, I just want to jump into the tests. So what I do is: I create all of the test data at the bottom of the file. I feel that this makes the unit tests much easier to read.
But since I want all of the test data to be available before the tests run, I wrap all of the tests in a function, create the test data, and then execute the function that contains all of the tests.
Example # 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
var testData = { months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }; describe('Service: ServiceA', () => { beforeEach(() => { TestBed.configureTestingModule({ providers: [ ServiceA, {provide: Window, useValue: window} ] }); }); describe('the test', () => { it(' should...', inject([ ServiceA ], (ServiceA) => { expect(testData.months.length).toEqual(12); })); }); }); |
In example # 1, I’ve set up a unit test. The test data is at the top of the file, which to me make the test hard to read.
Example # 2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
function runTests() { beforeEach(() => { TestBed.configureTestingModule({ providers: [ ServiceA, {provide: Window, useValue: window} ] }); }); describe('the test', () => { it(' should...', inject([ ServiceA ], (ServiceA) => { expect(testData.months.length).toEqual(12); })); }); } var testData = { months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }; //run the tests runTests(); |
In example # 2, I wrapped the unit tests in the function: runTests. This way I create the tests, create the test data, and then execute the runTests function. I like this approach because my test data is at the bottom of the file, and the actual unit test is at the top, which I feel makes the code easier to read.
After upgrading to Angular 4 (and subsequently upgrading the npm packages karma & karma-jasmine), I got a whole bunch of instances of this error: ERROR in [at-loader] Duplicate function implementation. I don’t get the error if there is only one unit test, but as soon as I introduce more than one unit-test file, I get the error (and the more files there are, the more errors there are).
This took a bit to figure out, but I finally got it. My runTests function is a global, and Jasmine does not like when there is more than one instance of it declared.
Example # 3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
function runTests_ServiceA() { beforeEach(() => { TestBed.configureTestingModule({ providers: [ ServiceA, {provide: Window, useValue: window} ] }); }); describe('the test', () => { it(' should...', inject([ ServiceA ], (ServiceA) => { expect(testData.months.length).toEqual(12); })); }); } var testData = { months: [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ] }; //run the tests runTests_ServiceA(); |
In example # 3, I renamed the runTests function to runTests_ServiceA. And in each unit test file, I did the same exact thing. For example: runTests_ServiceB, runTests_ServiceC, runTests_ServiceD, etc…
This way, each runTests function has a unique name. While I don’t always have test data, this is just a pattern I like to follow. The latest versions of the karma & karma-jasmine npm packages did not like the fact that multiple instance of the runTests function were being declared, so I just make sure that in each unit test file, that function has a unique name. An easy way to do this is to simply append “_ServiceName” to runTests. But as long as the function name is unique, any name will do.