Angular 4 使用 window 对代码进行单元测试
Angular 4 Unit Testing the code using window
我想测试一个代码
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);
}
}
我不知道如何访问 window 或模拟 window 以对其进行测试。我是 angular 测试的新手,所以如果你能详细解释我就太好了!
您也可以在测试中访问 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
describe 块的 beforeEach
块中,我将它分配给一个对象,该对象包含一个名为 getFile
的键,其值作为一个函数,最终将 return字符串 foo
.
此外,由于默认情况下您的测试是 运行 in Chrome,因此您不会在 window.navigator
对象上获得 msSaveOrOpenBlob
函数。所以 openAttachment
describe 块中的第一个测试只会覆盖 else 块。
虽然在第二个测试中,我们在 window.navigator
对象上添加了 msSaveOrOpenBlob
作为函数。所以现在它可以覆盖 if
分支。那么你可以在 msSaveOrOpenBlob
函数上创建一个间谍 expect
这个间谍 toHaveBeenCalledWith
无论是 return 从 attachment.getFile()
方法(字符串 foo
在这种情况下)
希望这对您有所帮助。
beforeEach(() => {
//使用下面的行
(<any>window).navigator ={ function msSaveOrOpenBlob() {} };
fixture = TestBed.createComponent(Your_Component);
component = fixture.componentInstance;
fixture.detectChanges();
}
我想测试一个代码
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);
}
}
我不知道如何访问 window 或模拟 window 以对其进行测试。我是 angular 测试的新手,所以如果你能详细解释我就太好了!
您也可以在测试中访问 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
describe 块的 beforeEach
块中,我将它分配给一个对象,该对象包含一个名为 getFile
的键,其值作为一个函数,最终将 return字符串 foo
.
此外,由于默认情况下您的测试是 运行 in Chrome,因此您不会在 window.navigator
对象上获得 msSaveOrOpenBlob
函数。所以 openAttachment
describe 块中的第一个测试只会覆盖 else 块。
虽然在第二个测试中,我们在 window.navigator
对象上添加了 msSaveOrOpenBlob
作为函数。所以现在它可以覆盖 if
分支。那么你可以在 msSaveOrOpenBlob
函数上创建一个间谍 expect
这个间谍 toHaveBeenCalledWith
无论是 return 从 attachment.getFile()
方法(字符串 foo
在这种情况下)
希望这对您有所帮助。
beforeEach(() => {
//使用下面的行
(<any>window).navigator ={ function msSaveOrOpenBlob() {} };
fixture = TestBed.createComponent(Your_Component);
component = fixture.componentInstance;
fixture.detectChanges();
}