You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
});

原有代码失效原因

  1. 直接触发re-captcha组件的click事件无效:组件内部封装了Google的验证逻辑,外部点击组件本身不会触发验证流程
  2. 触发resolved事件时未传入Token参数:导致submitReCaptcha接收到空值,所以控制台输出为空

内容的提问来源于stack exchange,提问作者phebus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:37:35