1. ホーム
  2. javascript

[解決済み] ジェスト あるクラスの特定のメソッドをモックする方法

2022-07-08 02:49:50

質問

以下のようなクラスがあるとします。

export default class Person {
    constructor(first, last) {
        this.first = first;
        this.last = last;
    }
    sayMyName() {
        console.log(this.first + " " + this.last);
    }
    bla() {
        return "bla";
    }
}

メソッド 'sayMyName' がモック化され、メソッド 'bla' がそのまま残るようなモック化されたクラスを作りたい場合を考えてみましょう。

私が書いたテストは

const Person = require("../Person");

jest.mock('../Person', () => {
    return jest.fn().mockImplementation(() => {
        return {sayMyName: () => {
            return 'Hello'
        }};
    });
});


let person = new Person();
test('MyTest', () => {
    expect(person.sayMyName()).toBe("Hello");
    expect(person.bla()).toBe("bla");
})

最初の'expect'文はパスします。つまり、'sayMyName'のモックが成功したことを意味します。しかし、2つ目の'expect'はエラーで失敗しています。

TypeError: person.bla は関数ではありません。

モックされたクラスがすべてのメソッドを消去することは理解しました。 特定のメソッドだけがモックされるようなクラスのモック方法を知りたいです。

どのように解決するのですか?

2021年03月05日を編集

多くの人が以下のアプローチに反対しているようですが、それはクールなことです。しかし、私は@bladeのアプローチに少し異論があります。というのも、それは実際にクラスをテストしていないのです。 mockImplementation . もしクラスが変更されたとしても、テストは常に偽陽性を与えて通過します。そこで、次の例では spyOn .

// person.js
export default class Person {
  constructor(first, last) {
      this.first = first;
      this.last = last;
  }
  sayMyName() {
      return this.first + " " + this.last; // Adjusted to return a value
  }
  bla() {
      return "bla";
  }
}


とテストします。

import Person from './'

describe('Person class', () => {
  const person = new Person('Guy', 'Smiley')

  // Spying on the actual methods of the Person class
  jest.spyOn(person, 'sayMyName')
  jest.spyOn(person, 'bla')
  
  it('should return out the first and last name', () => {  
    expect(person.sayMyName()).toEqual('Guy Smiley') // deterministic 
    expect(person.sayMyName).toHaveBeenCalledTimes(1)
  });
  it('should return bla when blah is called', () => {
    expect(person.bla()).toEqual('bla')
    expect(person.bla).toHaveBeenCalledTimes(1)
  })
});

乾杯! ????


モック化された実装が実際に何かを解決してくれるとは思えませんね。これはもう少し理にかなっていると思います。

import Person from "./Person";

describe("Person", () => {
  it("should...", () => {
    const sayMyName = Person.prototype.sayMyName = jest.fn();
    const person = new Person('guy', 'smiley');
    const expected = {
      first: 'guy',
      last: 'smiley'
    }

    person.sayMyName();

    expect(sayMyName).toHaveBeenCalledTimes(1);
    expect(person).toEqual(expected);
  });
});