Is there a way to create to use CreateSpyObj to create a spy of all methods in a class?

Viewed 2459

I'm writing unit tests for my Angular app and I'm learning about how to use spies.

Currently, every service that my component uses, I have to write something like this

let fakeMyService = jasmine.createSpyObj('fakeMyService', ['method1', 'method2']);
fakeMyService.method1.and.returnValue(Observable.of());
fakeMyService.method2.and.returnValue(Observable.of());

TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        { provide: MyService, useValue: fakeMyService }
      ]
    }).compileComponents();

Although this works, it doesn't seem like the best way to set up my spies. For one, I have to type every single function in MyService that I want to put spies in. Secondly, it's not strongly typed. So if I ever change the name, I won't know immediately and also then, I'll have to update it in every place.

Is there some sort of way where I can just specify the class and it'll automatically just return me a fake class with spies for all the methods?

So something like this

  let fakeMyService = jasmine.createSpyObj<MyService>();
4 Answers

Try using the new spyOnAllFunctions feature:

let fakeMyService = spyOnAllFunctions(MyService);

be aware that this is a new feature and it's available only in the latest 3.x version of Jasmine.

Also be aware that this feature is not yet present in the current typing (@types/jasmine). There is a feature request about it here.

I wrote my own function to do this:

function getMock(c) {
  return jasmine.createSpyObj(Object.getOwnPropertyNames(c.prototype));
}

All you have to do now to create a spy of all methods of a class is:

let fakeMyService = getMock(MyFakeService);

If you want type checks

let fakeService: MyService = spyOnAllFunctions<MyService>(MyService.prototype);
fakeProductRepository.method1 = () => {
  return null
}
Related