最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2 unit testing with ngModel - Stack Overflow

programmeradmin4浏览0评论

I am using the latest angular-cli with angular 2.1. The ponent test I want to write is simple: Get some data from a service and display it.

It works, when the data ist simply displayed in a paragraph, but it does not, when it is bound to a textarea.

Below is an excerpt from my template:

<p *ngIf="!isBusy" class="twain">
  <i>{{settings.blockLoginMessage}}</i>
</p>
<textarea  
  id="blockLoginMessage" 
  name="blockLoginMessage" 
  [(ngModel)]="settings.blockLoginMessage" 
  class="form-control">
</textarea>

and the corresponding tests:

describe('SettingsComponent', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [SharedModule, TranslateModule.forRoot()],
            declarations: [SettingsComponent],
            providers: [
                Overlay,
                ToastsManager,
                ViewContainerRef,
                TranslateService,
                SettingsService
            ]
        });

        fixture = TestBed.createComponent(SettingsComponent);
        p = fixtureponentInstance;

        settingsService = fixture.debugElement.injector.get(SettingsService);

        getSettingsSpy = spyOn(settingsService, 'getSettings')
            .and.returnValue(Observable.of(new Settings(true, false, 'test')).delay(500).toPromise());

        setSettingsSpy = spyOn(settingsService, 'setSettings')
            .and.returnValue(Observable.of(true).delay(500));

        fixture.detectChanges(); 
    });

    it('should create the ponent', () => {
        expect(p).toBeTruthy();
    });

    it('should show busy indicator as long as there are no settings', () => {
        let busyPanel = fixture.debugElement.query(By.css('#busyPanel'));
        expect(busyPanel).not.toBeNull('cant find busy');
    });

    it('should show loaded settings after observable finished (done)', done => {
        fixture.detectChanges();

        // get the spy promise and wait for it to resolve
        getSettingsSpy.calls.mostRecent().returnValue.then(() => {
            fixture.detectChanges();

            let de = fixture.debugElement.query(By.css('.twain'));
            let el = de.nativeElement;

            expect(el.textContent).toBe('test', 'show loaded settings');

            let de2 = fixture.debugElement.query(By.css('#blockLoginMessage'));
            let el2: HTMLTextAreaElement = de2.nativeElement;

            expect(el2.textContent).toBe('test', 'show loaded settings');

            done();
        });
    });
});

Does anyone have a hint why this does not work?

Furthermore, my attempts with async and fakeAsync fail pletely, when I have a delay in my promises like above.

I am using the latest angular-cli with angular 2.1. The ponent test I want to write is simple: Get some data from a service and display it.

It works, when the data ist simply displayed in a paragraph, but it does not, when it is bound to a textarea.

Below is an excerpt from my template:

<p *ngIf="!isBusy" class="twain">
  <i>{{settings.blockLoginMessage}}</i>
</p>
<textarea  
  id="blockLoginMessage" 
  name="blockLoginMessage" 
  [(ngModel)]="settings.blockLoginMessage" 
  class="form-control">
</textarea>

and the corresponding tests:

describe('SettingsComponent', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [SharedModule, TranslateModule.forRoot()],
            declarations: [SettingsComponent],
            providers: [
                Overlay,
                ToastsManager,
                ViewContainerRef,
                TranslateService,
                SettingsService
            ]
        });

        fixture = TestBed.createComponent(SettingsComponent);
        p = fixture.ponentInstance;

        settingsService = fixture.debugElement.injector.get(SettingsService);

        getSettingsSpy = spyOn(settingsService, 'getSettings')
            .and.returnValue(Observable.of(new Settings(true, false, 'test')).delay(500).toPromise());

        setSettingsSpy = spyOn(settingsService, 'setSettings')
            .and.returnValue(Observable.of(true).delay(500));

        fixture.detectChanges(); 
    });

    it('should create the ponent', () => {
        expect(p).toBeTruthy();
    });

    it('should show busy indicator as long as there are no settings', () => {
        let busyPanel = fixture.debugElement.query(By.css('#busyPanel'));
        expect(busyPanel).not.toBeNull('cant find busy');
    });

    it('should show loaded settings after observable finished (done)', done => {
        fixture.detectChanges();

        // get the spy promise and wait for it to resolve
        getSettingsSpy.calls.mostRecent().returnValue.then(() => {
            fixture.detectChanges();

            let de = fixture.debugElement.query(By.css('.twain'));
            let el = de.nativeElement;

            expect(el.textContent).toBe('test', 'show loaded settings');

            let de2 = fixture.debugElement.query(By.css('#blockLoginMessage'));
            let el2: HTMLTextAreaElement = de2.nativeElement;

            expect(el2.textContent).toBe('test', 'show loaded settings');

            done();
        });
    });
});

Does anyone have a hint why this does not work?

Furthermore, my attempts with async and fakeAsync fail pletely, when I have a delay in my promises like above.

Share Improve this question edited Oct 11, 2019 at 5:50 ggorlen 58k8 gold badges114 silver badges157 bronze badges asked Oct 25, 2016 at 5:42 Mattes83Mattes83 311 silver badge4 bronze badges 3
  • fixture.isStable() returns false btw – Mattes83 Commented Oct 25, 2016 at 5:50
  • Can you post a plete example, preferably just using a dummy ponent, and service, all posted in one page we can copy and paste and test as is. And please include only what is necessary to reproduce the problem (i.e. no translate module) or anything else that doesn't involve solving the problem of how to test ngModel. This is what an MVCE is – Paul Samsotha Commented Oct 25, 2016 at 6:12
  • pls check Angular 2 Testing: Get Value from ngModel – Long De Commented Jul 13, 2017 at 7:16
Add a ment  | 

1 Answer 1

Reset to default 8

ngModel updates asynchronously since RC5. You should test it asynchronous way:

it('should check initial value of ngModel', async(() => {
  let fixture = TestBed.createComponent(TestComponent);
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    let el = fixture.debugElement.query(By.css('select your input'));
    let actual = selectElement.nativeElement.value;
    expect(expected).toBe(actual);
  });
}));
发布评论

评论列表(0)

  1. 暂无评论