在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 并不是最佳做法,但在我能想到的方法中似乎是最好的选择。如果还有其他更好的方法,我想了解一下。

广告
将在 10 秒后关闭
bannerAds