Error: Expected spy create to have been called
Solution 1
Expected spy create to have been called is not an Error but a failed test.
This is happening because you haven't use callThrough(); on your spyOn either.
it('should submit Registration Form', async(inject([Router], (router) => {
myService = TestBed.get(GuestUserService);
mySpy = spyOn(myService, 'create').and.callThrough(); //callThrough()
spyOn(router, 'navigate');
spyOn(component, 'submitRegistrationForm').and.callThrough(); //callThrough()
component.submitRegistrationForm();
expect(component.profileForm.invalid).toBe(false);
expect(component.submitRegistrationForm).toHaveBeenCalled();
expect(myService).toBeDefined();
expect(mySpy).toBeDefined();
expect(mySpy).toHaveBeenCalledTimes(1);
expect(router.navigate).toHaveBeenCalled();
})
));
Solution 2
The spyOn
will help you to setup how the function should react when it's being called upon in your tests. Basically it's Jasmines way of creating mocks.
In your case you have defined what the test should do when the service function is being called, which is callThrough
. The problem is that you also need to act on the service function (or the scope function which calls your service method) in order to trigger the spyOn
which will callThrough
.
it('load snapshot',function(){
//setup
spyOn(MyService, 'loadSomething').and.callThrough(); //statement 2
//act
//either call the scope function which uses the service
//$scope.yourServiceCallFunction();
//or call the service function directly
MyService.loadSomething(1); //this will callThrough
});
Here's an simple test where we will mock the response of the spyOn
to a string
it('test loadSomething',function(){
//setup
spyOn(MyService, 'loadSomething').and.returnValue('Mocked');
//act
var val = MyService.loadSomething(1);
//check
expect(val).toEqual('Mocked');
});
Related videos on Youtube
Comments
-
Arjun Singh about 4 years
I'm writing unit test cases in angular 7 for a Component with async service and getting this error:
Error: Expected spy create to have been called once. It was called 0 times.
Here is my Component:
export class RegistrationComponent implements OnInit { submitRegistrationForm() { if (this.profileForm.invalid) { this.validateAllFields(this.profileForm); } else { // send a http request to save this data this.guestUserService.create(this.profileForm.value).subscribe( result => { if (result) { console.log('result', result); this.router.navigate(['/login']); } }, error => { console.log('error', error); }); } }
Unit test case:
describe('RegistrationComponent', () => { let component: RegistrationComponent; let fixture: ComponentFixture<RegistrationComponent>; let myService; let mySpy; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [RegistrationComponent], imports: [ ], providers: [ { provide: GuestUserService, useValue: new MyServiceStub() }] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(RegistrationComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should submit Registration Form', async(inject([Router], (router) => { myService = TestBed.get(GuestUserService); mySpy = spyOn(myService, 'create'); spyOn(router, 'navigate'); spyOn(component, 'submitRegistrationForm'); component.profileForm.controls['firstName'].setValue('Arjun'); component.profileForm.controls['lastName'].setValue('Singh'); component.profileForm.controls['password'].setValue('12345678'); component.profileForm.controls['confirmPassword'].setValue('12345678'); component.submitRegistrationForm(); expect(component.profileForm.invalid).toBe(false); expect(component.submitRegistrationForm).toHaveBeenCalled(); expect(myService).toBeDefined(); expect(mySpy).toBeDefined(); expect(mySpy).toHaveBeenCalledTimes(1); // Getting error is this expect(router.navigate).toHaveBeenCalled(); }) ));
I tried to move the spy deceleration in beforeEach but still its giving the same error.
how to fix this error?
Thanks!
-
user2216584 almost 5 yearsCan you change your line showing error like this and try -
expect(myService .create).toHaveBeenCalledTimes(1);
-
The Head Rush almost 5 yearsYou need to either
detectChanges
or calldone
(after injecting it) after calling the method under test and before your expects. -
Arjun Singh almost 5 yearsHello @user2216584, I have tried this expect(myService .create).toHaveBeenCalledTimes(1); but still getting the same error :(
-
Arjun Singh almost 5 yearsHi @TheHeadRush, fixture.detectChanges(); didn't worked as well.
-
user2216584 almost 5 years@ArjunSingh It appears that your component's else condition is not being executed. Put
console.log
inif
andelse
condition and see what gets logs. By seeing your test case it appears that your component'sthis.profileForm
is invalid and because of that yoursubmitRegistrationForm
method's else condition is not being executed. Are you sure that else condition ofsubmitRegistrationForm
is called? put logs and check. -
Arjun Singh almost 5 years@user2216584, No profileForm values are set and getting this.profileForm.invalid as false i.e else condition needs to be executed. Updated the test case.
-
-
Bidisha Das over 2 yearsThank you for this. It works wonder with form controls.