单元测试依赖于其他 getter 的 Vuex getter
Posted
技术标签:
【中文标题】单元测试依赖于其他 getter 的 Vuex getter【英文标题】:Unit test Vuex getters that depend on other getters 【发布时间】:2018-09-29 05:14:34 【问题描述】:我已经设法测试了与其他代码隔离的 Vuex getter。当一个 getter 依赖于其他 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: '***'
;
describe('getFoo', () =>
it('return name with prefix', () =>
expect(getters.getFoo(state)('name')).toBe('name: ***');
);
);
describe('getFancyNames', () =>
// mock getters
const _getters =
getFoo: getters.getFoo(state)
it('returns a collection of fancy names', () =>
expect(getters.getFancyNames(state, _getters)).toEqual([
'foo: ***',
'bar: ***'
]);
);
);
当测试的 getter 依赖于具有参数的其他 getter 时,这意味着我在 mock 上引用了原始的 getter.getFoo
,这打破了 mocking 的想法,因为测试开始相互关联。当 getter 增长,并且依赖图有几个级别时,它会使测试变得复杂。
也许这是要走的路,只是想检查一下我没有遗漏任何东西......
【问题讨论】:
【参考方案1】:我同意你的观点,在你的模拟中引用实际的合作者违背了模拟的目的。因此,我会直接返回您希望您的合作者返回的任何内容。
在您的示例中,不要这样做:
// mock getters
const _getters =
getFoo: getters.getFoo(state)
您只需输入getters.getFoo(state)
将返回的任何内容:
const _getters =
getFoo: 'foobar'
如果您有一个带有附加参数的 getter,您只需返回一个返回常量的函数:
const _getters =
getFoo: x => 'foobar',
【讨论】:
问题是您的测试实际上会运行原始的 getter,然后测试不会通过,因为您的 mock 包含生成与 getter 输出不同的输出。 不确定我是否在关注。您的测试运行将模拟的 getter 作为参数的 getter。我实际上在我的一个项目中使用这种方法。你能举个例子说明这会如何破坏你的测试吗? 哦,对不起,我想我现在看到了。您的getFancyNames
方法使用不同的参数两次调用相同的 getter。我的例子意味着你在这两种情况下都会返回foobar
。
感谢您的宝贵时间。你是对的它有效,我想在大多数情况下返回相同的值将是解决方案,甚至是最好的解决方案,因为你想隔离你的吸气剂测试。我已经发布了一个答案,因为我找到了一种使用jest
实现此目的的方法,以防您感到好奇;)【参考方案2】:
由于我使用的是 Jest,所以在 jest 模拟函数中有一个选项,让我们在调用时指定返回值:
mockReturnValueOnce
或 mockReturnValue
更多信息可以在这里找到:https://facebook.github.io/jest/docs/en/mock-functions.html#mock-return-values
使用与问题中相同的代码,可以这样解决:
const state =
name: '***'
describe('getFancyNames', () =>
const getFoo = jest.fn()
getFoo.mockReturnValueOnce('foo: ***')
getFoo.mockReturnValueOnce('bar: ***')
it('returns a collection of fancy names', () =>
expect(getters.getFancyNames(state, getFoo )).toEqual([
'foo: ***',
'bar: ***'
])
)
)
【讨论】:
【参考方案3】:我发现的一种更简洁的方法是创建自己的模拟 getters 对象。这仅在 getter
像问题一样使用未更改的 state
时才有效。
const state =
name: '***'
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: ***',
'bar: ***'
])
)
)
额外
如果您确实需要调用其他 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!
【讨论】:
以上是关于单元测试依赖于其他 getter 的 Vuex getter的主要内容,如果未能解决你的问题,请参考以下文章
无法读取未定义的属性“getters” - 带有笑话的 VueJS 单元测试
如何在 Mocha 单元测试中访问命名空间的 Vuex getter