Angular reCaptcha V2测试:如何模拟点击并获取Token
Angular测试中模拟reCaptcha V2获取Token的方法
我是Angular新手,正在测试中尝试获取reCaptcha Token。如何模拟点击reCaptcha的“我不是机器人”复选框,并在测试中记录Token响应?我使用的是reCaptcha V2版本,目前尝试了多种方法但均未成功。
index.component.html代码片段:
<div class="d-flex justify-content-center"> <re-captcha #recaptcha (resolved)="submitReCaptcha($event)" [siteKey]="siteKey" theme="dark" formControlName="recaptcha"></re-captcha> </div>
待测试的index.component.ts方法:
@ViewChild('recaptcha', { static: false, read: RecaptchaComponent }) repactcha?: RecaptchaComponent siteKey: string = environment.contactFormSiteKey submitReCaptcha(token: any) { // 处理Token逻辑 }
测试类方法(原有尝试):
it('on click it should retrieve a token', () => { const fixture = TestBed.createComponent(IndexComponent); fixture.detectChanges(); // 通知TestBed执行数据绑定 const component = fixture.componentInstance; // 访问组件属性和方法 const debug = fixture.debugElement; // 测试辅助对象 const native = fixture.nativeElement; // DOM对象 var token = ''; spyOn(component, 'submitReCaptcha').and.callFake((arg: any) => { token = arg; }) const debugEl = debug.query(By.css('re-captcha')); const nativeEl = native.getElementsByTagName('re-captcha')[0]; nativeEl.setAttribute('size', 'invisible'); debugEl.triggerEventHandler('resolved'); console.log(token); })
如前所述,我对Angular还不太熟悉,完全不理解测试方法中的逻辑。在此场景下,获取reCaptcha Token字符串的简便方法是什么?我在测试方法中尝试过debugEl.triggerEventHandler('click');但没有效果,也尝试了其他几种变体。
解决方案
在Angular单元测试中,我们不需要调用真实的Google reCaptcha服务,核心是验证自己代码的逻辑正确性,直接模拟组件行为即可,以下是两种简便可行的方法:
方法一:直接触发resolved事件传入模拟Token
组件已通过(resolved)绑定了submitReCaptcha方法,无需模拟真实点击,直接手动触发事件并传入自定义Token:
it('触发resolved事件时应正确接收Token', () => { const fixture = TestBed.createComponent(IndexComponent); fixture.detectChanges(); const component = fixture.componentInstance; const recaptchaEl = fixture.debugElement.query(By.css('re-captcha')); // 定义模拟的测试Token const mockToken = 'test-recaptcha-token-123'; let receivedToken = ''; // 监听submitReCaptcha方法,捕获传入的Token spyOn(component, 'submitReCaptcha').and.callFake((token) => { receivedToken = token; }); // 直接触发resolved事件并传入模拟Token recaptchaEl.triggerEventHandler('resolved', mockToken); // 验证方法被正确调用,且Token匹配 expect(component.submitReCaptcha).toHaveBeenCalledWith(mockToken); expect(receivedToken).toBe(mockToken); });
方法二:调用组件实例的execute方法(针对ng-recaptcha库)
如果你使用的是ng-recaptcha库,RecaptchaComponent提供了execute()方法可手动触发验证,直接模拟该方法返回Token即可:
it('调用execute方法应获取Token', async () => { const fixture = TestBed.createComponent(IndexComponent); fixture.detectChanges(); const component = fixture.componentInstance; // 等待ViewChild初始化完成 await fixture.whenStable(); const mockToken = 'test-recaptcha-token-456'; let receivedToken = ''; spyOn(component, 'submitReCaptcha').and.callFake((token) => { receivedToken = token; }); // 模拟execute方法返回Token spyOn(component.repactcha!, 'execute').and.returnValue(Promise.resolve(mockToken)); // 调用execute方法 await component.repactcha!.execute(); // 验证结果 expect(component.submitReCaptcha).toHaveBeenCalledWith(mockToken); expect(receivedToken).toBe(mockToken); });
原有代码失效原因
- 直接触发
re-captcha组件的click事件无效:组件内部封装了Google的验证逻辑,外部点击组件本身不会触发验证流程 - 触发
resolved事件时未传入Token参数:导致submitReCaptcha接收到空值,所以控制台输出为空
内容的提问来源于stack exchange,提问作者phebus
相关产品推荐
相关产品推荐

