-
-
Notifications
You must be signed in to change notification settings - Fork 7
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.
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
})
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);
})