LoginSignup
0

Angularのテストでenvironmentの変数をモックする

Posted at

environment で宣言した変数についてテストの書き方に迷ったのでメモしておく。

  • Angular v15
  • @testing-library/angular v13
  • jest v28

environment

Angular にはローカル・本番など、環境ごとに変数を切り替える機能がある。

// src/environment/environment.{環境}.ts
export const environment = {
  production: false,
  foo: "FOO"
};

environment は任意のコンポーネントやサービスで参照することができる。

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 パターンしか作れない

.... :thinking: どれもイマイチ。

採用したテストコード

結果、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();
  });
});

この方法なら、別のテストファイルで environment の別パターンを用意することもできる。

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 を呼べないなどベストとは言えないが、思いついた方法の中ではいちばん良さそう。他にいい方法があれば知りたい。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0