Unit testing a simple utility class

I now want to start trying to add some unit tests (after not being able to get it working some time ago). Ive downloaded and run the example here, and also followed the documentation here.

Previously, one of the first things I tried to test (before even getting to any UI related test), was a couple of simple utility classes. One was a simple Dictionary (lookup)

It is declared as follows…

import { Utils } from './utils';

export class Dictionary<T> {
   constructor(private noCase?: boolean, init?: Array<{ key: string; value: T; }>) {
   ....
   }
}

I’ve installed everything as in the example, and just ran npm run test before adding any to make sure it all seemed to work, which it did (ran 0 tests)

I’ve added a dictionary.spec.ts file, with the following contents…

import { Dictionary } from './dictionary';

let dictionary : Dictionary<string> = null;
describe('Dictionary', () => {
     beforeEach(() => {
        dictionary = new Dictionary<string>(true, []);
    });
   
  it('should have containsKey find a value added', () => {
      dictionary.add("a", "A Val");
      let exists = dictionary.containsKey("a");
      expect(exists).toBeTruthy()
     });

    it('should have containsKey not find a value not added', () => {
      dictionary.add("a", "A Val");
      let exists = dictionary.containsKey("b");
      expect(exists).toBeFalsy()
     });
});

But when I run it (npm run test), I get the following error about the classes constructor not existing…

$ npm run test

> myapp@ test D:\dev\myapp
> karma start ./test-config/karma.conf.js


webpack: Compiled successfully.
webpack: Compiling...
ts-loader: Using typescript@2.3.0 and D:\dev\myapp\tsconfig.json
11 09 2017 21:25:10.646:WARN [karma]: No captured browser, open http://localhost:9876/

webpack: Compiled successfully.
11 09 2017 21:25:10.662:INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/
11 09 2017 21:25:10.662:INFO [launcher]: Launching browser Chrome with unlimited concurrency
11 09 2017 21:25:10.824:INFO [launcher]: Starting browser Chrome
11 09 2017 21:25:12.156:INFO [Chrome 60.0.3112 (Windows 10 0.0.0)]: Connected on socket cKWnS_4e_ReULXXkAAAA with id 4991384
Chrome 60.0.3112 (Windows 10 0.0.0) ERROR
  Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_3__dictionary__.a is not a constructor
  at webpack:///src/shared/utils.ts:19:17 <- test-config/karma-test-shim.js:77758
Chrome 60.0.3112 (Windows 10 0.0.0) ERROR
  Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_3__dictionary__.a is not a constructor
  at webpack:///src/shared/utils.ts:19:17 <- test-config/karma-test-shim.js:77758
Chrome 60.0.3112 (Windows 10 0.0.0): Executed 0 of 0 ERROR (0.422 secs / 0 secs)
webpack: Compiling...

I do see the imported class Utils in there. This is actually a class full of static helpers. It has no constructor, and it just declared as…

export class Utils {
  }

It has quite a few imports, not sure if this matters?

I am new to all the test utils used here (jasmine, karma etc).

Does anyone know why this doesn’t work? Is it because I have optional parameters, or the class is a generic?

(I have another class that fails too, but will put that in a different post)

Thanks in advance for any help!

It appears my problem is the imported Utils class. In the dictionary class, there are calls to a couple of basic static methods on the Utils class.

So the Utils class just has a whole lot of “utils”, e.g. string compares, string formatting, argument guards, etc It looks like the following

import * as moment from 'moment';
import 'moment-duration-format';
import * as _ from 'lodash';
import { TranslateService } from 'ng2-translate';
import { Dictionary } from './dictionary';
.....


export class Utils {
  public static guard(obj: any, name: string): void {
    if (obj == null || obj == undefined)
      throw (name + " must not be null!");
  }

   public static guardS(s: string, name: string): void {
    if (this.isNullorEmptyOrWhiteSpace(s))
      throw (name + " must not be null or empty!");
   }

  ...  etc
  }

Then in dictionary, I use a couple of these static methods…

public add(key: string, value: T): void {
    Utils.guardS(key, "key");
    Utils.guard(value, "value");

Is there a way to test a class that uses such a static class within it?
Do I somehow have to mock this static utils class?

“have to”? No, but I would suggest that it’s probably a good idea. I would also ditch moment for date-fns.

My actual problem was a “circular” import, ie I used the Dictionary in the Utils class

import { Dictionary } from './dictionary';

If I removed that, I could (if wanted) use the Utils class. I’ll have to look into the mocking (of statics) for future use though.

1 Like