简体   繁体   中英

How to pass a Jasmine spy object as a provider using Angular TestBed

I wish to use Angular's (version 7) TestBed to test a component, and see if an injected service has a method called.

Watching this this tutorial , around 23:18 he show how to create a Jasmine sky, so you can then use test methods such as toHaveBeenCalledTimes

I am trying to do the same thing, except using TestBed to create the component rather than instantiating manually as in the video.

I have the following..

describe('AppComponent', () => {
    beforeEach(async(() => {
        
        fakeStartupService = jasmine.createSpyObj(fakeStartupService, ['start']);
        //fakeStartupService.start.and.returnValue(null);
                        
        TestBed.configureTestingModule({
            imports: [
                RouterTestingModule,
            ],
            providers: [
                ErrorHandler,
                { provide: StartupService, useValue: fakeStartupService },
            ],
            declarations: [
                AppComponent,        
            ],
                        
        }).compileComponents();     
    }));
    
    it('should have called start services start'), () => {
        expect(fakeStartupService.start).toHaveBeenCalledTimes(100);
    } 
});

The first question, is when I type expect(fakeStartupService. I do not get the code completion to show the start method as they do in the video.

The other (main) question, is although the above compiles and runs, I don't think I have it correct as the expect(fakeStartupService.start).toHaveBeenCalledTimes(100); does not fail - the component only calls it once, but I am asserting 100 times, so it should fail.

I took a guess at using the useValue in the { provide: StartupService, useValue: fakeStartupService }, , so perhaps this is incorrect

I would like to know

  • is using a spy like this possible, and if so how can I do this?

Thanks in advance

[UPDATE1]

Actually I had a syntax error (bracket after the description).

The following seems to work for me.

it('should have called start services start once',  async () => {
  const fixture = TestBed.createComponent(AppComponent);    
  const app = fixture.debugElement.componentInstance;

  // As ngOnInit is async, use detectChanges and whenStable to wait for it to be finished.
  fixture.detectChanges();
  await fixture.whenStable()      
  expect(fakeStartupService.start).toHaveBeenCalledTimes(1);    
});

Also, to wait for me async ngOnInit I added the

 fixture.detectChanges();
 await fixture.whenStable()     

Now, the only minor question was how in the video they got the intellisense.

I watched part of the video, that is not intellisense/autocomplete. Well, in a way it is, where it is coming from Visual Studio Code and the IDE is matching (and trying its best) what you're typing to what has been typed before in the document. I hope this makes sense.

To get true intellisense and autocomplete in this situation, create an interface somewhere in your project called spied.ts with the following definition:

export type Spied<T> = {
  [Method in keyof T]: jasmine.Spy;
};

Then when you define fakeStartupService , do it like so:

import { Spied } from './where/spied/type/file/was/saved';
....
let fakeStartupService: Spied<StartupService>;

Now when you type fakeStarupService.st , autocomplete/intellisense of start should come up.

I use this and I got this from this article: https://pragmatic-coder.net/typesafe-jasmine-spies/ . Scroll down to The fix .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM