我想了解如何使用Angular中创建的依赖项来测试服务。该服务只有一种方法可以打开Angular Material Snackbar,并且不返回任何内容。根据条件,有两种显示方式-成功或错误。该服务没有公共属性,所有操作均以其包含的唯一方法完成。该服务还具有一些依赖性。伪代码如下:
export class SnackbarService {
constructor(private snackBar: MatSnackBar, private status: Status) { }
openSnackBar(arg: string | Error):void {
let prop1: string;
let prop2: number;
let prop3: string;
if (arg instanceof Error) {
prop1 = this.status.default;
prop2 = 5000;
prop3 = 'error';
} else {
prop1 = 'another status';
prop2 = 6000;
prop3 = 'success';
}
this.snackBar.open(prop1, 'x', {
prop2,
horizontalPosition: 'center',
verticalPosition: 'top',
prop3
});
}
现在进行测试。我以为,测试上述服务是否将以另一种方式编写可能会更容易-将公共属性作为参数传递给两个方法而不是一个方法-一个解决if
语句的方法和另一个实际上打开的方法小吃店。但是,让我们说代码看起来像上面。当方法不返回任何内容且没有公共属性时,可以实际测试什么?
describe('SnackbarService', () => {
let service: SnackbarService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MatSnackBarModule
],
providers: [
SnackbarService
]
});
service = TestBed.inject(SnackbarService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
我知道应该将依赖项导入到测试中,但是除了创建服务本身之外,不知道如何测试其他任何东西。感谢任何建设性的提示!
答案 0 :(得分:1)
自从MatSnackBar
被注入依赖项以来,您可以对其进行模拟,窥探其open
方法,并验证传递给它的参数。
因此您的测试设置应如下所示:
const mockMatSnackBar = {
open: () => {}
};
const mockStatus = {
default: ''
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
],
providers: [
SnackbarService,
{ provide: MatSnackBar, useValue: mockMatSnackBar }, // <--- use mock
{ provide: Status, useValue: mockStatus } // <--- use mock
]
});
service = TestBed.inject(SnackbarService);
matSnackBar = TestBed.inject(MatSnackBar);
});
您的测试将如下所示:监视open
方法并验证其调用的参数:
it('calls the MatSnackBar open method with status, "x", and a config object', () => {
const matSnackBarSpy = spyOn(matSnackBar, 'open').and.stub();
service.openSnackBar('arg');
expect(matSnackBarSpy.calls.count()).toBe(1);
const args = matSnackBarSpy.calls.argsFor(0);
expect(args.length).toBe(3);
expect(args[0]).toBe('another status');
expect(args[1]).toBe('x');
expect(args[2]).toEqual({
prop2: 6000,
horizontalPosition: 'center',
verticalPosition: 'top',
prop3: 'success'
});
});
Here's a StackBlitz显示了这种方法。
答案 1 :(得分:0)
您可以验证它应该打开。
styles
答案 2 :(得分:0)
根据昨天的一些提示(其中一些已经消失),Jasmine docs和this post,我能够编写一些基本测试(注释和working StackBlitz中的描述)
describe("SnackbarService", () => {
let service: SnackbarService;
// mocking service
const mockSnackbarService = jasmine.createSpyObj("SnackbarService", [
"openSnackBar"
]);
beforeEach(() => {
TestBed.configureTestingModule({
// providing the service and mock into the Testbed
providers: [{ provide: SnackbarService, useValue: mockSnackbarService }]
});
// injecting the service
service = TestBed.inject(SnackbarService);
});
it("should be created", () => {
expect(service).toBeTruthy();
});
describe("openSnackBar", () => {
it("should open the snack bar", () => {
const arg = "test";
// calling mock
mockSnackbarService.openSnackBar.and.callThrough();
// calling service method with argument
service.openSnackBar(arg);
// checking if method has been called
expect(service.openSnackBar).toHaveBeenCalled();
});
});
});