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

Ember 3.0采用RFC 268格式的验收重定向测试无限挂起

解决Ember 3.0 RFC268格式验收测试无限挂起的问题

首先,咱们拆解下你遇到的核心问题:旧版moduleForAcceptance测试正常,但改用RFC268的setupApplicationTest+async/await后,测试卡在await visit()处无限挂起,控制台还没报错。这大概率是新测试模式和旧模式的行为差异导致的,咱们一步步分析解决。

可能遗漏的关键点

1. 路由钩子中的异步操作未正确收尾

Ember 3.0的新测试助手(比如visit)会严格等待所有异步操作完成(包括路由钩子中的Promise、数据加载等)才会resolve,而旧版andThen的等待逻辑没这么严格。如果你的受保护路由的beforeModel/afterModel钩子中有异步逻辑(比如session验证、异步数据请求),但没正确处理Promise的resolve,就会导致await visit()一直挂起。

举个反例,你的路由如果是这样写的:

// app/routes/protected.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default Route.extend({
  session: service(),

  async beforeModel() {
    // 未await session异步加载,也没返回transitionTo的Promise
    if (!this.session.isAuthenticated) {
      this.transitionTo('login');
    }
  }
});

改成这样就能解决:

async beforeModel() {
  // 确保session的异步操作完成
  await this.session.loadCurrentUser();
  if (!this.session.isAuthenticated) {
    // 返回transitionTo的Promise,让测试感知重定向操作已完成
    return this.transitionTo('login');
  }
}

2. 测试助手的导入不正确

确认你是从@ember/test-helpers导入visit、currentURL这些助手,而不是依赖旧版的全局助手。新测试模式下全局助手默认禁用,导入错误会导致行为异常:

// 正确导入方式
import { visit, currentURL } from '@ember/test-helpers';

3. 未检查应用中是否有未解决的全局Promise

如果你的应用初始化阶段(比如路由、服务)有一直pending的Promise,新测试的await visit()会一直等待所有异步任务settle。可以在浏览器控制台执行Ember.run.backburner.queues查看未处理任务,或者用pauseTest()调试:

test('visiting /protected redirects to /login', async function(assert) {
  await visit('/protected');
  pauseTest(); // 在这里暂停,查看应用状态和未解决的Promise
  assert.equal(currentURL(), '/login');
});

更好的重定向测试方法

为了让测试更可靠、更快,建议模拟session的状态,而非依赖真实的session服务初始化。这样测试不需要等待真实异步请求,还能隔离外部依赖:

import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, currentURL } from '@ember/test-helpers';

module('Acceptance | unauthenticated redirect', function(hooks) {
  setupApplicationTest(hooks);

  test('unauthenticated user is redirected to /login', async function(assert) {
    // 直接模拟session未认证状态
    let session = this.owner.lookup('service:session');
    session.set('isAuthenticated', false);

    await visit('/protected');
    assert.equal(currentURL(), '/login', '未认证用户被重定向到登录页');
  });

  test('authenticated user can access protected page', async function(assert) {
    // 模拟已认证状态,验证重定向逻辑不触发
    let session = this.owner.lookup('service:session');
    session.set('isAuthenticated', true);

    await visit('/protected');
    assert.equal(currentURL(), '/protected', '已认证用户可访问受保护页面');
  });
});

这种方式不仅能快速验证重定向逻辑,还能覆盖正反两种场景,测试更全面。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:17:45