Angular 4 Unit使用窗口测试代码

时间:2017-10-10 15:29:04

标签: angular testing jasmine window karma-jasmine

我想测试代码

public openAttachment(attachment: Attachment) {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(attachment.getFile());
    }
    else {
        let objectUrl = URL.createObjectURL(attachment.getFile());
        window.open(objectUrl);
    }
}

我不知道如何访问窗口或模拟窗口以进行测试。我是角度测试的新手,所以如果你能详细解释我的话会很棒!

2 个答案:

答案 0 :(得分:5)

您也可以在测试中访问window对象。所以你可以很容易地监视他们。

我已经为您的特定用例创建了一个轻量级组件。

以下是组件:



import { Component } from '@angular/core';

@Component({
  selector: 'app-attachment',
  templateUrl: './attachment.component.html',
  styleUrls: ['./attachment.component.css']
})
export class AttachmentComponent {

  public openAttachment(attachment) {
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(attachment.getFile());
    }
    else {
      let objectUrl = URL.createObjectURL(attachment.getFile());
      window.open(objectUrl);
    }
  }

}




请注意,我不确定Attachment类型是什么。因此,我已将参数中的类型注释删除到openAttachment函数。

现在我的测试应该是这样的:



import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { AttachmentComponent } from './attachment.component';

describe('AttachmentComponent', () => {
  let component: AttachmentComponent;
  let fixture: ComponentFixture<AttachmentComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AttachmentComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AttachmentComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });

  describe('openAttachment', () => {
    let attachment;
    beforeEach(() => {
      attachment = { getFile: function() { return 'foo'; } };
    });

    it('should call `window.open` if `msSaveOrOpenBlob` is not a method present on the `window.navigator`', () => {

      // Since this will probably run on Chrome, Chrome Headless or PhantomJS, if won't have a `msSaveOrOpenBlob` method on it.
      // So this is the test for the else condition.
      let windowOpenSpy = spyOn(window, 'open');
      let returnValue = { foo: 'bar' };
      let urlCreateObjectSpy = spyOn(URL, 'createObjectURL').and.returnValue(returnValue);

      component.openAttachment(attachment);

      expect(urlCreateObjectSpy).toHaveBeenCalledWith('foo');
      expect(windowOpenSpy).toHaveBeenCalledWith(returnValue);

    });

    it('should call the `window.navigator.msSaveOrOpenBlob` if `msSaveOrOpenBlob` is present on the navigator object', () => {

      // To cover the if condition, we'll have to attach a `msSaveOrOpenBlob` method on the window.navigator object.
      // We can then spy on it and check whether that spy was called or not.
      // Our implementation will have to return a boolean because that's what is the return type of `msSaveOrOpenBlob`.
      window.navigator.msSaveOrOpenBlob = function() { return true; };
      let msSaveOrOpenBlobSpy = spyOn(window.navigator, 'msSaveOrOpenBlob');

      component.openAttachment(attachment);

      expect(msSaveOrOpenBlobSpy).toHaveBeenCalledWith('foo');

    });

  });

});
&#13;
&#13;
&#13;

我再次强调一个事实,即我不确定附件类型是什么。因此,在我的beforeEach describe块的openAttachment块中,我将其分配给包含名为getFile的键的对象,其值为最终将返回字符串的函数foo

此外,由于您的测试默认情况下会在Chrome中运行,因此您无法在msSaveOrOpenBlob对象上获得window.navigator功能。所以openAttachment describe块中的第一个测试只会覆盖else块。

在第二个测试中,我们已将msSaveOrOpenBlob添加为window.navigator对象的函数。所以现在它可以覆盖if分支。那么你可以在msSaveOrOpenBlob函数和expect这个间谍toHaveBeenCalledWith上创建一个间谍,无论从attachment.getFile()方法返回什么(在这种情况下为字符串foo

希望这有帮助。

答案 1 :(得分:0)

beforeEach(() => {

//使用下面的行

 (<any>window).navigator ={ function msSaveOrOpenBlob() {} };

   fixture = TestBed.createComponent(Your_Component);
   component = fixture.componentInstance;

   fixture.detectChanges();
}