单元测试依赖于其他getter的Vuex getter

时间:2018-04-18 20:32:34

标签: javascript unit-testing vue.js vuex jest

我已经设法测试与其他代码隔离的Vuex getter。当吸气剂依赖于其他吸气剂时,我现在面临一些问题,请参见以下示例:

getters.js

export const getters = {

  getFoo(state) => prefix {
    return `${prefix}: ${state.name}`;
  },

  getFancyNames(state, getters) {
    return [
      getters.getFoo('foo'),
      getters.getFoo('bar')
    ]
  }
}

getters.spec.js

import { getters } = './getters';

const state = {
  name: 'stackoverflow'
};

describe('getFoo', () => {

  it('return name with prefix', () => {
    expect(getters.getFoo(state)('name')).toBe('name: stackoverflow');
  });

});

describe('getFancyNames', () => {

  // mock getters
  const _getters = {
    getFoo: getters.getFoo(state)
  }

  it('returns a collection of fancy names', () => {
    expect(getters.getFancyNames(state, _getters)).toEqual([
      'foo: stackoverflow',
      'bar: stackoverflow'
    ]);
  });
});

当测试的getter依赖于具有参数的其他getter时,这意味着我在模拟上引用了原始的getter.getFoo,这打破了模拟的想法,因为测试开始彼此关系。当getter增长,并且依赖图有几个级别时,它会使测试变得复杂。

也许这是要走的路,只是想检查一下我没有遗漏任何东西......

3 个答案:

答案 0 :(得分:2)

我同意你的观点,在模拟中引用实际的协作者会破坏模拟的目的。因此,我只需直接返回您希望协作者返回的任何内容。

在你的例子中,而不是做这样的事情:

actionPerformed

你只需输入javax.swing.Timer将返回的任何内容:

$datetime = new DateTime('2013-01-29');
$datetime->modify('+1 day');
echo $datetime->format('Y-m-d H:i:s');

如果你有一个带有额外参数的getter,你只需返回一个返回常量的函数:

// mock getters
const _getters = {
  getFoo: getters.getFoo(state)
}

答案 1 :(得分:0)

由于我使用Jest,在jest模拟函数中有一个选项,让我们在调用时指定返回值:

mockReturnValueOncemockReturnValue

可在此处找到更多信息:https://facebook.github.io/jest/docs/en/mock-functions.html#mock-return-values

使用与问题相同的代码,可以这样解决:

const state = {
  name: 'stackoverflow'
}

describe('getFancyNames', () => {
  const getFoo = jest.fn()
  getFoo.mockReturnValueOnce('foo: stackoverflow')
  getFoo.mockReturnValueOnce('bar: stackoverflow')

  it('returns a collection of fancy names', () => {
    expect(getters.getFancyNames(state, { getFoo })).toEqual([
      'foo: stackoverflow',
      'bar: stackoverflow'
    ])
  })
})

答案 2 :(得分:0)

我发现的一种更简洁的方法是创建您自己的模拟 getter 对象。这仅在 getter 像问题一样使用未更改的 state 时有效。

const state = {
  name: 'stackoverflow'
}

describe('getFancyNames', () => {
  const mockedGetters = {
    ...getters,  // This can be skipped
    getFoo: getters.getFoo(state),  // We only overwrite what is needed
  };

  it('returns a collection of fancy names', () => {
    expect(getters.getFancyNames(state, mockedGetters)).toEqual([
      'foo: stackoverflow',
      'bar: stackoverflow'
    ])
  })
})

额外

如果您确实需要调用其他 getter 函数,只需将模拟的 getter 对象传递给另一个模拟的 getter 对象。听起来比实际情况更糟。

getters.py

export const getters = {

  getBar(state) = {   // new extra hard part!
    return state.bar,
  },

  getFoo(state, getters) => prefix {
    return `${prefix}: ${state.name} with some ${getters.getBar}`;
  },

  getFancyNames(state, getters) {
    return [
      getters.getFoo('foo'),
      getters.getFoo('bar')
    ]
  }
}
const _mockedGetters = {
  ...getters,  // This can be skipped
  getFoo: getters.getFoo(state),  // We only overwrite what is needed
};

const mockedGetters = {
  .._mockedGetters,  // Use the mocked object!
  getBar: getters.getBar(state, _mockedGetters),  // We only overwrite what is needed
};

// continue down the line as needed!