【发布时间】:2019-09-06 02:29:45
【问题描述】:
在我们的应用程序中,我们需要根据当前用户是否经过身份验证来使用不同的端点。身份验证的状态存储在 Redux 状态中。这是我使用 redux 选择器的常见模式:
// selectors.js
import {selectIsAuthenticated} from 'Redux/customer/selectors'
export const selectEndpoint = state => selectIsAuthenticated(state) ? 'guest' : 'authenticated'
export const selectEndpointA = state => `/rest/${selectEndpoint(state)}/a`
export const selectEndpointB = state => `/rest/${selectEndpoint(state)}/b`
测试时,这变得复杂,因为我无法模拟 selectEndpoint.. 所以 selectEndpointA 的测试变得依赖于 selectEndpoint 的实现,这并不理想。
什么是测试这样的东西的正确方法或重构它以更容易测试?
我考虑过重构,以便将 selectEndpoint 作为selectEndpointA 的参数(或咖喱)传入,例如:
export const selectEndpointA = selectEndpoint => state => `/rest/${selectEndpoint(state)}/a`
但这似乎过于复杂,因为现在在我的代码中,我需要在任何我想使用的地方添加导入 selectEndpointA
编辑:
这是我的单元测试示例:
import * as selectors from 'Redux/global/selectors'
import * as customerSelectors from 'Redux/customer/selectors'
const nonAuthenticatedEndpoint = 'guest'
/* ... */
describe('selectEndpoint', () => {
it('returns proper endpoint for non authenticated user', () => {
customerSelectors.selectIsAuthenticated = jest.fn(() => false)
const state = 'state'
const expected = nonAuthenticatedEndpoint
expect(selectors.selectEndpoint(state)).toEqual(expected)
expect(customerSelectors.selectIsAuthenticated).toHaveBeenCalledWith(
state
)
})
}
所以Redux/global/selectors 内还有selectEndpointA 和selectEndpointB
编辑:
还有一个我想做的测试示例:
describe('selectEndpointA', () => {
it('returns correct endpoint for non authenticated user', () => {
const state = {
/* some specific state */
}
expect(selectors.selectEndpointA(state)).toEqual('/rest/guest/a')
})
})
虽然目前这确实有效,但我想找到一种方法将其与 selectEndpoint 的实现分离,并且比较值不依赖于 selectEndpoint 的返回
【问题讨论】:
-
如果你正在导出
selectEndpoint,你可以在你的测试中存根它,以便它返回你想要的。您能在测试文件中展示您尝试过的内容吗? -
@mgarcia 我确实为我的反应组件导出它,但我想直接测试我的选择器,主要是为了能够确定更改是否会破坏任何功能
-
@mgarcia 我的理解是 jest mocks 只适用于导入,所以因为这两个函数在同一个文件中,jest 没有办法创建一个 mock
标签: javascript unit-testing testing redux jestjs