【问题标题】:Angular 4 Unit Testing the code using windowAngular 4 使用窗口对代码进行单元测试
【发布时间】:2017-10-10 15:29:04
【问题描述】:

我想测试一段代码

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);
    }
}

我不知道如何访问窗口或模拟窗口以对其进行测试。我是角度测试的新手,如果您能详细解释一下,那就太好了!

【问题讨论】:

    标签: angular testing jasmine window karma-jasmine


    【解决方案1】:

    您也可以在测试中访问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');
    
        });
    
      });
    
    });

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

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

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

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:
      beforeEach(() => {
      

      //使用下面一行

       (<any>window).navigator ={ function msSaveOrOpenBlob() {} };
      
         fixture = TestBed.createComponent(Your_Component);
         component = fixture.componentInstance;
      
         fixture.detectChanges();
      }
      

      【讨论】:

      • 老实说,这对我来说已经足够好了。我们在窗口对象上有很多自定义属性,我在 SSO 上找到的很多其他答案包括很多额外的工作,包括更改我不喜欢的我们正在测试的代码。谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-15
      • 2014-01-06
      • 1970-01-01
      • 2013-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多