在Angular测试中模拟环境变量
因为对在环境中声明的变量的测试方法感到困惑,所以我将其记下来作为备忘。
-
- Angular v15
-
- @testing-library/angular v13
- jest v28
环境
Angular可以通过不同的环境(例如本地、生产环境)来切换变量。
// src/environment/environment.{環境}.ts
export const environment = {
production: false,
foo: "FOO"
};
环境可以通过任何组件或服务进行引用。
import { Component, Input, OnInit } from "@angular/core";
import { environment } from "src/environments/environment";
@Component({
standalone: true,
selector: "dummy",
template: `{{ env }}`,
})
export class DummyComponent implements OnInit {
@Input() name: string;
env = "";
ngOnInit(): void {
this.env = environment[this.name];
}
}
<dummy name="foo"></dummy>
// "FOO" がレンダリングされる
Angular应用程序的构建和服务 | angular.jp
考察测试
我思考了几种测试上述组件的方法。
-
- environment を参照するサービスを宣言して DI する
いかにもテストのためのサービスという感じで冗長な気がした
サービスの利用が強制できないため environment を DI したり直接インポートしたりばらつきが出る
environment のプロパティをテストコードから上書きする
別のテストファイルで再度 environment を参照した時の影響度が見えないので怖い
上書き禁止のために as const したら破綻する
environment.test.ts を追加しテスト環境の設定を切り分ける
1 パターンしか作れない
……哪一个都不太好。
使用的测试代码
结果,我们决定使用Jest的模块模拟。
import { render } from "@testing-library/angular";
import { screen } from "@testing-library/dom";
import { DummyComponent } from "src/app/dummy.component";
jest.mock("src/environments/environment", () => ({
environment: {
foo: "FOO",
},
}));
describe("test1", () => {
it("fooは存在するのでレンダリングされる", async () => {
await render(`<dummy [name]="name"></dummy>`, {
imports: [DummyComponent],
componentProperties: { name: "foo" },
});
expect(screen.getByText("FOO")).toBeInTheDocument();
});
it("barは存在しないのでレンダリングされない", async () => {
await render(`<dummy [name]="name"></dummy>`, {
imports: [DummyComponent],
componentProperties: { name: "bar" },
});
expect(screen.queryByText("BAR")).toBeNull();
});
});
如果采用这种方法,也可以在另一个测试文件中准备不同的环境模式。
jest.mock("src/environments/environment", () => ({
environment: {
bar: "BAR",
},
}));
describe("test2", () => {
it("foo", async () => {
await render(`<dummy [name]="name"></dummy>`, {
imports: [DummyComponent],
componentProperties: { name: "foo" },
});
// environment に foo は存在しない
expect(screen.queryByText("FOO")).toBeNull();
});
});
参考:Jest v28 中的模块模拟绕过功能。
虽然在同一个文件中多次调用 jest.mock 并不是最佳做法,但在我能想到的方法中似乎是最好的选择。如果还有其他更好的方法,我想了解一下。