如何修复单元测试 - 错误:“无法读取未定义的属性'parseUrl'”?

时间:2017-11-30 11:59:20

标签: angular unit-testing jasmine

对于使用Service I'am的组件编写单元测试 - spec文件。

组件中的功能:

registerUser(email: string, pass: string) {
    if (!this.EMAIL_REGEXP.test(email)) {
        return false;
    } else if (!this.PASS_REGEXP.test(pass)) {
        return false;
    } else {
        this._backUpApiService.storeUserData(email, pass)
        .subscribe(
            (res) => {
                console.log(JSON.stringfy(res));
                ...
            },
            (err) => {
                console.log(JSON.stringfy(err));
                ...
            }
        );
    }
}
服务中的

方法:

storeUserData(email:String, pass:String) {
    this.form = this._fbuilder.group({
        input: {
            user:{
                umail:email,
                upassword:pass
            }
        }
    });
    let formObj = this.form.getRawValue();
    let serializedObj = JSON.stringify(formObj);

    return this._http.post(url, serializedObj, this.options)
    .map(res => {
        res.json();
    })
    .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}

规范文件:

it(`should call storeUserData on BackendApiService when registerUser is called with correct Credentials`, async(() => {

    let myService: BackendApiService = new BackendApiService();
    spyOn(myService, 'storeUserData').and.returnValue(Observable.of(myService));

    const emailOk = [
      'test@test.com',
      'test@test.co.uk',
    ];
    const passwordOk = '!cdRef2';

    let result = component.registerUser(this.emailOk, this.passwordOk);

    expect(myService.storeUserData).toHaveBeenCalled();

  }));

问题是测试失败,我不断收到以下信息: Cannot read property 'parseUrl' of undefined

规范文件中的函数是否期望服务函数中的Ajax调用的 URL ?我实际上只想测试在调用/调用组件中的 storeUserData 函数时是否正在调用服务中的 registerUser 函数。

我做错了什么?

1 个答案:

答案 0 :(得分:1)

我不知道为什么你得到一个“无法读取属性'parseUrl'的未定义”错误,因为你的代码不包含对parseUrl的任何引用。

但是我可以看到一些错误:

第一个storeUserData实际上并没有从registerUser调用addUser是。

第二个registerUser期望传递一个字符串,就像它的电子邮件一样,你传递一个字符串数组。

修改

另外一个观察:

另一个错误的地方是您正在创建服务的新实例,而不是获取组件使用的服务实例。你需要使用:

const myService = TestBed.get(BackendApiService);

然后,您将实际监视组件使用的服务实例。这当然会假设您的服务被注入到组件的构造函数中。

如果你让spyOn正常工作,那么你确实不必担心storeUserData会发生什么,因为它永远不会被调用。错误可能来自唯一的另一个地方是您的服务的构造函数。我已创建服务存根类以注入我的测试,以便我的服务类依赖不会导致问题。对于你可能看起来像:

export class BackendApiServiceStub {
  storeUserData(email: String, pass: String) {
    return Observable.of([]);
  }
}

然后你需要在测试条中用存根替换真实的东西,如下所示:

TestBed.configureTestingModule({
  declarations: [
    AppComponent
  ],
  providers: [
    {provide: BackendApiService, useClass: BackendApiServiceStub }
  ]
}).compileComponents();

这应该可以阻止任何其他问题蔓延到您的测试中。