如何实施Jest Mocks?

时间:2019-01-21 11:34:45

标签: javascript mocking jestjs

我正在使用Jest框架,并试图实现功能的模拟。我有一个小型的机场应用程序,允许用户起飞和降落飞机,但由于随机天气而必须加以限制。

天气在另一类中并且是随机的,对于我的测试,我需要模拟weather函数以始终在一个测试中返回true,而在其他测试中返回false。

我遇到的困难是如何准确地实现模拟功能?文档谈论使用jest.fn并将其设置为常量变量,但这使我感到困惑,因为我不了解jest.fn在未提供函数名称时如何等同于函数。其他开玩笑的模拟文档虽然很全面,但对于学习的人来说却有点不可及,而我拥有的大多数其他资源也导致了同样的困惑。本质上,我希望外行的术语指南能够实现这一目标?例如-

  • 如何正确地将函数声明为模拟?
  • 如何显式声明该函数的返回值?
  • 如何在我的测试套件中调用该模拟函数?

测试:

const Airport = require('./airport')
const Plane = require('./plane')
const Weather = require('./weather')

airport = new Airport('Bristol')
plane = new Plane('Boeing 747')


test('the airport lands a plane', () => {
  expect(airport.land(plane)).toBe(1);
});

test('the airport allows a plane to take off', () =>{
  expect(airport.takeOff()).toBe(0);
});

test('the airport has a default capacity of 1 when constructed', () => {
  bath = new Airport('Bath')
  expect(bath.capacity).toBe(1)
})

test('The airports default capacity can be defined at construction', () => {
  bristol = new Airport('Bristol', 5)
  expect(bristol.capacity).toBe(5)
});

test("The airport doesn't let you land when the hangar is full", () => {
  wells = new Airport('Wells', 1)
  plane2 = new Plane('Spitfire')
  wells.land(plane)
  expect(wells.land(plane2)).toBe('HANGAR FULL LANDING DENIED')
});

test("The airport doesn't let you land when weather is stormy", () =>{
  york = new Airport('york', 1)
//  york.weather = true
  plane = new Plane('plane')
  expect(york.land(plane)).toEqual('LANDING DENIED POOR WEATHER')
});

正在测试的机场文件:

const Weather = require('./weather')

class Airport {
  constructor(name, capacity = 1, weather = new Weather) {
    this.name = name;
    this.hangar = [];
    this.capacity = capacity;
    this.weather = weather.getWeather();
  }

   land (plane) {
     if (this.weather === true) {
       return 'LANDING DENIED POOR WEATHER'
     } else if (this._isFull() === false) {
       this.hangar.push(plane)
     return this.hangar.length
   } else {
     return 'HANGAR FULL LANDING DENIED'
   }
   };


  takeOff () {
   this.hangar.pop()
   return this.hangar.length;
 };

  _isFull () {
   if (this.hangar.length < this.capacity) {
     return false
   } else {
     return true
   }
  };

};

module.exports = Airport;

具有随机天气功能的天气类别:

class Weather {

  getWeather() {
    var chance = Math.floor(Math.random() * 10)
    if (chance <= 3) { return true } else { return false }
  }
}

module.exports = Weather;

您可以在文件中看到我发现了一种替代天气的糟糕方法,方法是将Airport的属性手动设置为true,尽管如此,我仍然被告知这是一种代码味道,希望重构为适当的模拟功能/ module / class。

1 个答案:

答案 0 :(得分:0)

您的Airport类已设置为使用依赖注入来获取天气。

它将在传递给构造函数的第三个参数上调用getWeather(如果没有提供,则调用Weather的新实例)以设置Airport的天气。

您可以使用此依赖项注入来提供Weather依赖项的模拟实现,以设置测试所需的天气:

test("The airport doesn't let you land when weather is stormy", () =>{
  const york = new Airport('york', 1, { getWeather: () => true })  // always bad weather
  const plane = new Plane('plane')
  expect(york.land(plane)).toEqual('LANDING DENIED POOR WEATHER')  // SUCCESS
});