如何使用Jasmine为构造函数创建间谍

时间:2018-10-26 08:50:42

标签: angular jasmine karma-jasmine

我正在尝试使用Jasmine和Karma针对Angular编写我的第一个“复杂”测试。这是我要针对的测试代码:

function mb_remove_sidebar() {
    return false;
}

add_filter( 'is_active_sidebar', 'mb_remove_sidebar', 10, 2 );

我正在尝试为createForm方法编写测试:

import { Component, Inject } from "@angular/core";
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
import { Router } from "@angular/router";
import { AuthService } from '../../services/auth.service';

@Component({
   selector: "login",
   templateUrl: "./login.component.html",
   styleUrls: ['./login.component.css']
})

export class LoginComponent {

title: string;
form!: FormGroup;

constructor(private router: Router,
    private frmbuilder: FormBuilder,
    private authService: AuthService,
    @Inject('BASE_URL') private baseUrl: string) {

    this.title = "User Login";

    this.createForm();
}

createForm() {
    this.form = this.frmbuilder.group({
        Email: ['', Validators.required],
        Password: ['', Validators.required]
    });
}…

运行测试时,我收到以下错误消息:TypeError:严格模式函数或调用它们的参数对象上可能无法访问“ caller”,“ callee”和“ arguments”属性。

作为答案提供的链接不能解决我的问题。我认为这是因为我在构造函数中调用了createForm方法(完全有效,但很难测试)。如果我将import { TestBed, async } from '@angular/core/testing'; import { LoginComponent } from './login.component'; import { Router } from '@angular/router'; import { AuthService } from '../../services/auth.service'; import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms'; describe('create form', () => { let component : LoginComponent; let service : AuthService; let router: Router; let frmBuilder: FormBuilder; let spy : any; beforeEach(() => { spyOn(component, LoginComponent.arguments(router, frmBuilder, service)); component = new LoginComponent(router, frmBuilder, service, ''); }); it('expect the login form to have been created', () => { expect(component.createForm()).toHaveBeenCalled(); }); }); 中测试的第一行更改为beforeEach,那么我将收到错误spyOn(component,'createForm');

1 个答案:

答案 0 :(得分:0)

要侦察某个方法,您需要该方法所属的类的实例(被测系统或sut),以便可以用侦探替换该方法。

spyOn<any>(sut, 'initializeForm');

这意味着所涉及的类必须在侦察其方法或属性之前已被实例化,这对于侦察您在beforeEach方法中传递给构造函数的对象或属于sut的方法很容易做到。不是由构造函数本身调用的,而是之后。

但是由于您要检查构造函数是否正在调用该方法,但是您需要在调用构造函数之前需要该类的实例,以便监视由构造函数调用的方法,但实例化没有其构造函数的类构造函数是不可能的,您遇到了dilemma

我的建议是将您的方法调用移至ngOnInit方法并进行测试。

describe('constructor', () => {
    it('should create the sut', () => {
        expect(sut).toBeDefined();
    });
});

describe('ngOnInit', () => {
    it('should call initializeForm', () => {
        spyOn<any>(sut, 'initializeForm');

        sut.ngOnInit();

        expect(sut.initializeForm).toHaveBeenCalled();
    });
});

describe('initializeForm', () => {
    it('should initialize the form', () => {
        sut.initializeForm();

        expect(sut.form).toBeDefined();
    });
});

是的,可以在构造函数中创建简单的表单。但是随着事情变得越来越复杂,例如当您想访问@Input参数值时,ngOnInit方法是开始创建表单的最佳位置。

为了防止Angular引发模板错误,请在构造函数中提供表格的精简版本/空白版本,或者在ngOnInit运行通过并使用* ngIf定义表格之前,禁止呈现HTML。

<form *ngIf="form" [formGroup]="form">
  ...
</form>