Jasmine 角度测试用例返回TypeError:\u this.reCaptchaApi.render不是函数

Jasmine 角度测试用例返回TypeError:\u this.reCaptchaApi.render不是函数,jasmine,angular5,karma-jasmine,angular-test,Jasmine,Angular5,Karma Jasmine,Angular Test,我已经以6种反应形式实现了ngx验证码。该功能对我来说运行良好,但当我运行单元测试用例时,测试用例失败,并显示以下消息: TypeError:_this.reCaptchaApi.render不是函数 我在两个组件中实现了ngx验证码(可见类型)。对于这两个组件,功能对我来说都很好,但是在单元测试用例运行期间,我遇到了上面提到的错误 我尝试了以下方法: captcha-test.html <ngx-recaptcha2 #captchaElem [siteKey]="captchaSite

我已经以6种反应形式实现了ngx验证码。该功能对我来说运行良好,但当我运行单元测试用例时,测试用例失败,并显示以下消息:

TypeError:_this.reCaptchaApi.render不是函数

我在两个组件中实现了ngx验证码(可见类型)。对于这两个组件,功能对我来说都很好,但是在单元测试用例运行期间,我遇到了上面提到的错误

我尝试了以下方法:

captcha-test.html

<ngx-recaptcha2 #captchaElem [siteKey]="captchaSiteKey" 
formControlName="captcha"> </ngx-recaptcha2>
//验证码-test.spec.ts

import { async, ComponentFixture, TestBed } from 
"@angular/core/testing";
import { HttpClientModule } from "@angular/common/http";
import { CaptchaTestComponent } from "./captcha-test.component";
import { BrowserAnimationsModule } from "@angular/platform- 
browser/animations";
import { RouterTestingModule } from "@angular/router/testing";
import { MatProgressSpinnerModule, MatFormFieldModule, MatInputModule } 
from "@angular/material";
import { ReactiveFormsModule, FormBuilder } from "@angular/forms";
import { TestConstants } from "src/app/test/constants";
import { NgxCaptchaModule } from "ngx-captcha";

describe("CaptchaTestComponent", () => {
jasmine.getEnv().allowRespy(true);
let fixture: ComponentFixture<CaptchaTestComponent>;

beforeEach(async(function () {
TestBed.configureTestingModule({
  imports: [RouterTestingModule, BrowserAnimationsModule,
    ReactiveFormsModule, HttpClientModule, MatProgressSpinnerModule,
    MatFormFieldModule, MatInputModule, NgxCaptchaModule],
  providers: [FormBuilder
  ],
  declarations: [CaptchaTestComponent]
  }).compileComponents();
}));

beforeEach(function () {
 fixture = TestBed.createComponent(CaptchaTestComponent);
 this.component = fixture.componentInstance;
 this.component.captchaExampleForm.controls["captcha"].setValue(TestConstan ts.validCaptcha); //manually set a string data as input data.

fixture.detectChanges();
});

it("should init component properly", function () {
  this.component.ngOnInit();
  expect(this.component.captchaExampleForm).toBeDefined();
});

it("should return submit as false when we submit the form", async 
  function () {
    const result = await this.component.exapmleFormSubmit();
    expect(result).toBeFalsy();
  });
});
import{async,ComponentFixture,TestBed}from
“@角度/核心/测试”;
从“@angular/common/http”导入{HttpClientModule};
从“/captcha test.component”导入{CaptchaTestComponent};
从“@angular/platform-
浏览器/动画”;
从“@angular/router/testing”导入{RouterTestingModule}”;
导入{MatProgressSpinnerModule,MatFormFieldModule,MatInputModule}
从“@角度/材料”;
从“@angular/forms”导入{ReactiveFormsModule,FormBuilder}”;
从“src/app/test/constants”导入{TestConstants};
从“ngx验证码”导入{NgxCaptchaModule};
描述(“CaptChatTestComponent”,()=>{
jasmine.getEnv().allowRespy(true);
let夹具:组件夹具;
beforeach(异步(函数(){
TestBed.configureTestingModule({
导入:[RouterTestingModule,BrowserAnimationsModule,
反应窗体模块、HttpClientModule、MatProgressSpinnerModule、,
MatFormFieldModule、MatInputModule、NGxCaptChamModule],
提供者:[表单生成器]
],
声明:[CaptChatTestComponent]
}).compileComponents();
}));
beforeach(函数(){
fixture=TestBed.createComponent(CaptchaTestComponent);
this.component=fixture.componentInstance;
this.component.captcheaexampleform.controls[“captcha”].setValue(TestConstan ts.validCaptcha);//手动将字符串数据设置为输入数据。
fixture.detectChanges();
});
它(“应该正确初始化组件”,函数(){
this.component.ngOnInit();
expect(this.component.captchexampleform).toBeDefined();
});
它(“当我们提交表单时,应该将submit返回为false”),异步
函数(){
const result=wait this.component.exapmleFormSubmit();
expect(result.toBeFalsy();
});
});

我正在使用“ngx验证码”:“^5.0.4”版本和Angular 6。

看起来这是一个时间问题。我把你目前发布的内容放到一个文件夹中,以复制你的问题。正如你在StackBlitz中看到的,这两个测试现在都通过了

我对测试套件所做的更改是在第二个
beforeach()
中更改调用fixture.detectChanges()的顺序。在更改之前,它看起来是这样的:

beforeEach(function () {
  fixture = TestBed.createComponent(CaptchaTestComponent);
  this.component = fixture.componentInstance;
  this.component.captchaExampleForm.controls["captcha"].setValue(TestConstants.validCaptcha); //manually set a string data as input data.
  fixture.detectChanges();
});
beforeEach(function () {
  fixture = TestBed.createComponent(CaptchaTestComponent);
  this.component = fixture.componentInstance;
  fixture.detectChanges();
  this.component.captchaExampleForm.controls["captcha"].setValue(TestConstants.validCaptcha); //manually set a string data as input data.
});
在更改之后,它看起来是这样的:

beforeEach(function () {
  fixture = TestBed.createComponent(CaptchaTestComponent);
  this.component = fixture.componentInstance;
  this.component.captchaExampleForm.controls["captcha"].setValue(TestConstants.validCaptcha); //manually set a string data as input data.
  fixture.detectChanges();
});
beforeEach(function () {
  fixture = TestBed.createComponent(CaptchaTestComponent);
  this.component = fixture.componentInstance;
  fixture.detectChanges();
  this.component.captchaExampleForm.controls["captcha"].setValue(TestConstants.validCaptcha); //manually set a string data as input data.
});
这之所以重要是因为
fixture.detectChanges()
调用
ngOnInit()
,并且您在
ngOnInit()中设置了表单。如果在设置表单之前尝试使用
setValue
修改表单,则该表单将不起作用。鸡和蛋的问题。:)


我希望这会有所帮助。

我已经通过覆盖包含ngx-recaptcha2组件的模块解决了这个问题

Recaptcha V2的模拟组件

从“@angular/core”导入{Component,Input,forwardRef};
从“@angular/forms”导入{NG_VALUE_ACCESSOR}”;
从“/control\u value\u accessor.mock”导入{MockControlValueAccessor}”;
@组成部分({
//tslint:禁用下一行:组件选择器
选择器:“ngx-recaptcha2”,
模板:“”,
供应商:[
{
提供:NG_值访问器,
useExisting:forwardRef(()=>MockRecaptchaV2Component),
多:真的
},
]
})
导出类MockRecaptchaV2Component扩展了MockControlValueAccessor{
@Input()siteKey:字符串;
}

Recaptcha正在使用formControlName,因此我们需要以下模拟类

从“@angular/forms”导入{ControlValueAccessor};
导出类MockControlValueAccessor实现ControlValueAccessor{
writeValue(对象:任意):无效{
}
注册变更(fn:任何):无效{
}
注册人(fn:任何):无效{
}
setDisabledState?(isDisabled:boolean):无效{
}
}
我们现在需要使用以下代码覆盖NgxCaptchaModule模块

beforeach(异步(函数)(){
TestBed.configureTestingModule({
导入:[浏览动画模块,反应表单模块,ngxcaptchamule],
声明:[SignupComponent,MockRecaptchaV2Component],
}).overrideModule(NgxCaptchaModule{
删除:{
//需要SignupComponent,因为ReCaptcha2Component用作SignupComponent中的子组件
声明:[SignupComponent,ReCaptcha2Component],
导出:[注册组件,重述组件]
}
}).compileComponents();
}));

在我看来,这是迄今为止最干净的解决方案,只需在导入中使用ng mocks包并模拟NgxCaptchaModule即可

beforeach(异步(()=>{
TestBed.configureTestingModule({
进口:[
//其他进口
模拟模块(NgxCaptchaModule),
],
声明:[
注册组件
]
}).compileComponents();
}));

Protip:模拟所有组件和模块。使用此策略将增加组件中测试的隔离度

请包含您尝试的整个.spec文件。我在问题部分添加了.spec文件。多谢各位@dmcgrandlethis不起作用,我们仍然会得到相同的渲染错误,但有时它会通过,所以在执行测试时是否存在任何竞争条件的可能性?很有趣。在这次闪电战中,它似乎一直在通过。也许您可以将StackBlitz转移到您自己的帐户,并使用组件和模板中的所有数据进行更新。这段代码中可能有些东西