Autospy - gparlakov/scuri GitHub Wiki
Autospy
The goal of autospy is to spare you the boilerplate of creating a mock (spy in jasmine parlance).
It takes a TS class and creates mocks for all methods in its prototype. It then returns an object with the type that allows it to be used as the original type as well as in .hasBeenCalledWith assertions that require a different shape object.
Example
In this example our UserComponent depends on UserService and we'd like to test that when ngOnInit is called it calls UserService.current() method once.
// user.ts
class UserService {
current(): User {
//...
}
}
// user.component.ts
class UserComponent {
constructor(private user: User) {}
ngOnInit(){
this.current = this.user.current();
}
}
For that, we would need to instantiate the dependency UserService, the component-under-test UserComponent and call the ngOnInit method in our test file:
//user.component.spec.ts
it('calls current', () => {
// arrange
const userSpy = autoSpy(UserService);
// used as the UserService type here ๐
const userComponent = new UserComponent(userSpy);
// act
userComponent.ngOnInit();
// assert
//used as the spy-able type here ๐
expect(userSpy.current).toHaveBeenCalledTimes(1);
// i.e.๐userSpy has๐current property that can be spied upon
})
Properties
Autospy does not, and (currently) can not create spies for the properties of a class. That's because properties are not part of the prototype and run-time autospy code has no way of detecting them. What to do then? We can assign values to these properties just as we would in our code.
Continuing the example from above:
// user.ts
class UserService {
// ๐ our dependency has a property - not visible in the prototype, though
isAuthenticated: boolean;
current(): User {
//...
}
}
// user.component.ts
class UserComponent {
constructor(private user: User) {}
ngOnInit(){
this.current = this.user.current();
if(this.user.isAuthenticated) {
this.content = userAuthenticatedContent;
}
}
}
For that, we would need to instantiate the dependency UserService, the component-under-test UserComponent and call the ngOnInit method in our test file:
//user.component.spec.ts
it('shows the authenticated user content', () => {
// arrange
const userSpy = autoSpy(UserService);
// set the property ๐ here
userSpy.isAuthenticated = true;
const userComponent = new UserComponent(userSpy);
const authContent = 'This user is indeed authenticated!'
// act
userComponent.ngOnInit();
// assert
expect(userComponent.content).toEqual(authContent);
})