1
votes

I've made a hello world app at the moment which fetches the string "hello world" from my API when a button is pressed.

I have some experience with unit testing and was wondering whether I am separating concerns correctly.

The tests I plan on doing are:

  1. Test that the button click calls the GET method just once.
  2. Test that the function returns the string hello world.

So the questions I have are:

  1. Is it possible to check how many times functions are called?
  2. The controller where the function is implemented is in typescript in a separate file, can someone point me in the correct direction to test typescript controller functions and also how to write jasmine tests in TS.

Thanks,

1

1 Answers

0
votes

In jasmine 2.x it is possible to check the number of times a function has been called like this (this is of course assuming you are spying on said function):

expect(myservice.someFunction.calls.count()).toBe(someNumber);

Writing Jasmine test in TS is very similar to JS. The only real difference as far as I have experienced is the syntax. You will have strong typing for your variables now and instead of doing your it and describe blocks with functions you will use fat arrow syntax. So instead of

describe('Test', function() {
    it('true is true', function() {
        expect(true).toBe(true);
    })
})

You will write your test like this

describe('Test', () => {
    it('true is true', () => {
        expect(true).toBe(true);
    })
})

Here is a small contrived sample of test I've written in TS.

namespace UserList.Services.Tests {

describe("UserList: GetEntityTypeService", () => {
    let service: UserList.Services.GetEntityTypeService;

    beforeEach(() => {
        angular.mock.module("App.UserList.Module");

        angular.mock.module(($provide: angular.auto.IProvideService) => {
            $provide.service("UserList.Services.GetEntityTypeService", UserList.Services.GetEntityTypeService);
        });

        inject(($injector: angular.auto.IInjectorService) => {
            service = <UserList.Services.GeteEntityTypeService>($injector.get("UserList.Services.GetEntityTypeService"));
        });
    });

    it("should be defined", () => {
        expect(service).toBeDefined();
    });
});

}

Remember TS is a superset of JS. So any valid JS is valid TS. You could write your test in plain JS if you really wanted to and it would still work.

As for your question about separating concerns, I think you are on the right track. Here is a pattern that I follow that works very well.

  • Describe the object with type and name.
  • Load the object's module.
  • Load mock modules as needed.
  • Inject dependencies and spy on methods.
  • Initialize the object:
    • Services just need to get injected.
    • Controllers are instantiated using the $controller service.
    • We need to $compile directives.
  • Write expectations grouped in describe blocks.

Test for state, synchronous and async calls to services, and events, and expected outcomes when necessary.