如何在Ember集成测试中配置ember-intl服务?
解决Ember集成测试中ember-intl "No locale defined" 报错问题
你的问题我太熟悉了——旧版ember-intl文档的测试示例确实跟不上Ember的迭代节奏,尤其是moduleForComponent和container.lookup这些API早就被淘汰了。核心原因是集成测试环境里,ember-intl服务没被正确初始化:既没设置locale,也没加载翻译文件,导致组件调用翻译时直接报错。
下面给你两种实用的解决方案,根据你的测试需求选就行:
方案一:初始化真实的ember-intl服务(适合需要验证真实翻译的测试)
用新版Ember测试API,在beforeEach钩子中通过this.owner获取intl服务,手动设置locale并加载翻译:
import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; module('Integration | Component | x-product', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { // 获取intl服务(替代旧的container.lookup) const intlService = this.owner.lookup('service:intl'); // 设置测试用的locale intlService.setLocale('en-us'); // 如果你的翻译是按文件组织的,手动加载对应翻译(按需添加) // 比如你的en-us翻译在app/translations/en-us.js里: // intlService.addTranslations('en-us', require('my-app/translations/en-us').default); }); test('it renders with correct translations', async function(assert) { await render(hbs`{{x-product price=price deadline=deadline}}`); this.set('price', 1000); this.set('deadline', new Date()); // 替换成你实际要验证的翻译文本 assert.dom().containsText('Your translated price label here'); }); });
如果你的应用是通过ember-intl的构建流程自动注入翻译的,可能不需要手动调用addTranslations,但测试环境偶尔会有加载延迟,这时可以加个waitFor确保翻译加载完成。
方案二:存根intl服务(适合只验证组件逻辑的测试)
如果你的测试不需要关心真实翻译内容,只是想确保组件正确调用了翻译方法,直接存根intl的t方法更简单:
import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; import { stubService } from 'ember-qunit'; module('Integration | Component | x-product', function(hooks) { setupRenderingTest(hooks); hooks.beforeEach(function() { // 存根intl服务的t方法,直接返回key或者自定义文本 stubService('intl', { t(key) { // 可以返回带标记的key,方便测试断言 return `[TRANSLATED: ${key}]`; // 也可以针对特定key返回固定文本: // if (key === 'product.price') return 'Price:'; // return key; } }); }); test('it uses translation service', async function(assert) { await render(hbs`{{x-product}}`); // 验证存根的输出 assert.dom().containsText('[TRANSLATED: product.price]'); }); });
关键提醒
- 新版Ember测试中,
this.owner是获取容器内服务/对象的标准方式,替代了旧的this.container。 - 如果用的是组件级翻译(比如每个组件单独的translation文件),要么确保测试能加载到这些文件,要么用存根跳过真实翻译的依赖。
- 异步翻译加载的场景:如果你的翻译是异步加载的,记得用
await waitFor(...)等待翻译就绪后再做断言。
内容的提问来源于stack exchange,提问作者casafred
相关产品推荐
相关产品推荐

