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.