根据Jasmine文档,可以这样创建一个模拟:
jasmine.createSpyObj(someObject, ['method1', 'method2', ... ]);
您如何存根这些方法之一?例如,如果要测试方法抛出异常时会发生什么,该怎么办?
Answers:
正如EricG所评论的那样,您必须链接method1
,method2
但不能链接andCallThrough()
(或and.callThrough()
在2.0版中)。它将委托给实际的实现。
在这种情况下,您需要链接and.callFake()
并传递要调用的函数(可能引发异常或任何您想要的函数):
var someObject = jasmine.createSpyObj('someObject', [ 'method1', 'method2' ]);
someObject.method1.and.callFake(function() {
throw 'an-exception';
});
然后您可以验证:
expect(yourFncCallingMethod1).toThrow('an-exception');
.and.callFake()
,.and.callThrough()
,.and.returnValue()
jasmine.github.io/2.0/introduction.html#section-Spies
如果您使用的是Typescript,将方法转换为会很有帮助Jasmine.Spy
。在上述答案中(奇怪的是,我没有代表发表评论):
(someObject.method1 as Jasmine.Spy).and.callFake(function() {
throw 'an-exception';
});
我不知道自己是否过度设计,因为我缺乏知识...
对于打字稿,我想要:
我发现这很有用:
namespace Services {
class LogService {
info(message: string, ...optionalParams: any[]) {
if (optionalParams && optionalParams.length > 0) {
console.log(message, optionalParams);
return;
}
console.log(message);
}
}
}
class ExampleSystemUnderTest {
constructor(private log: Services.LogService) {
}
doIt() {
this.log.info('done');
}
}
// I export this in a common test file
// with other utils that all tests import
const asSpy = f => <jasmine.Spy>f;
describe('SomeTest', () => {
let log: Services.LogService;
let sut: ExampleSystemUnderTest;
// ARRANGE
beforeEach(() => {
log = jasmine.createSpyObj('log', ['info', 'error']);
sut = new ExampleSystemUnderTest(log);
});
it('should do', () => {
// ACT
sut.doIt();
// ASSERT
expect(asSpy(log.error)).not.toHaveBeenCalled();
expect(asSpy(log.info)).toHaveBeenCalledTimes(1);
expect(asSpy(log.info).calls.allArgs()).toEqual([
['done']
]);
});
});
todoService: {[key: string]: jasmine.Spy} = jasmine.createSpyObj(...); todoService.anyMethod.and....
无需每次都投射给间谍。
角度9
jasmine.createSpyObj
在测试注入了简单服务的组件时,使用是理想的选择。例如:假设在我的HomeComponent中有一个HomeService(注入)。HomeService中的唯一方法是getAddress()。创建HomeComponent测试套件时,我可以将组件和服务初始化为:
describe('Home Component', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
let element: DebugElement;
let homeServiceSpy: any;
let homeService: any;
beforeEach(async(() => {
homeServiceSpy = jasmine.createSpyObj('HomeService', ['getAddress']);
TestBed.configureTestingModule({
declarations: [HomeComponent],
providers: [{ provide: HomeService, useValue: homeServiceSpy }]
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
element = fixture.debugElement;
homeService = TestBed.get(HomeService);
fixture.detectChanges();
});
}));
it('should be created', () => {
expect(component).toBeTruthy();
});
it("should display home address", () => {
homeService.getAddress.and.returnValue(of('1221 Hub Street'));
fixture.detectChanges();
const address = element.queryAll(By.css(".address"));
expect(address[0].nativeNode.innerText).toEqual('1221 Hub Street');
});
});
这是使用来测试组件的简单方法jasmine.createSpyObj
。但是,如果您的服务具有更多方法和更复杂的逻辑,则建议您创建一个模拟服务而不是createSpyObj。例如:
providers: [{ provide: HomeService, useValue: MockHomeService }]
希望这可以帮助!
在@Eric Swanson的答案的基础上,我创建了一个更好的可读性和文档化的功能,供在测试中使用。我还通过将参数作为函数键入来添加一些类型安全性。
我建议将此代码放在通用测试类中的某个位置,以便可以将其导入每个需要它的测试文件中。
/**
* Transforms the given method into a jasmine spy so that jasmine functions
* can be called on this method without Typescript throwing an error
*
* @example
* `asSpy(translator.getDefaultLang).and.returnValue(null);`
* is equal to
* `(translator.getDefaultLang as jasmine.Spy).and.returnValue(null);`
*
* This function will be mostly used in combination with `jasmine.createSpyObj`, when you want
* to add custom behavior to a by jasmine created method
* @example
* `const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang'])
* asSpy(translator.getDefaultLang).and.returnValue(null);`
*
* @param {() => any} method - The method that should be types as a jasmine Spy
* @returns {jasmine.Spy} - The newly typed method
*/
export function asSpy(method: () => any): jasmine.Spy {
return method as jasmine.Spy;
}
用法如下:
import {asSpy} from "location/to/the/method";
const translator: TranslateService = jasmine.createSpyObj('TranslateService', ['getDefaultLang']);
asSpy(translator.getDefaultLang).and.returnValue(null);
andCallThrough
。没有明确记录:/