Language: Typescript (Angular Component Test)
Method to be tested:
methodToBeTested(ev) { ev.call(); }
Test:
it('test', () => { const ev = {call: () => {}}; // Run Test component.methodToBeTested(ev); // Controls expect(ev.call).toHaveBeenCalled(); });
Error: <call> : Expected a spy, but got Function.
Solution:
it('test', () => { const ev = {call: () => {}}; spyOn(ev, 'call'); // Run Test component.methodToBeTested(ev); // Controls expect(ev.call).toHaveBeenCalled(); });
This was easy, since the parameter ev does not have a type.
Method 2:
methodToBeTested(ev: TypeWithMultipleAttributes) { ev.call(); }
Test:
it('test', () => { const ev = {call: () => {}}; spyOn(ev, 'call'); // Run Test component.methodToBeTested(ev); // Controls expect(ev.call).toHaveBeenCalled(); });
Error: Argument of type {call: () => {}} is not assignable to parameter of type TypeWithMultipleAttributes. Property XXX is missing in type {call: () => {}}.
Reason: we did not create a constant with the correct type. So the content of our test data is very different than the one which we should prepare.
Solution 1: is to create our test data with the original type:
it('test', () => { const ev : TypeWithMultipleAttributes = {X: 1, Y: 'goh', call: () => {}, ...}; spyOn(ev, 'call'); // Run Test component.methodToBeTested(ev); // Controls expect(ev.call).toHaveBeenCalled(); });
Solution 2: What if the type has many attributes which we do not want to deal with.. In the end, we will just check if a method is called:
it('test', () => { const ev = {call: () => {}}; spyOn(ev, 'call'); // Run Test component.methodToBeTested(ev as TypeWithMultipleAttributes); // Controls expect(ev.call).toHaveBeenCalled(); });
as keyword takes our test object (which may have a different content), and passes it through the Typescript’s type validation. This seems like a hack, but cleverly eliminates the need for creating a specified type. Typically the test object should at least contain the attributes, the method in test needs. (In our project, we had a very complex type with more than 10 attributes, but in a specific location we wanted to test just a method call as shown above.)