t.true(wrapper.contains(<label>Email</label>), 'should render label')
const event = { target: { value: 'foo@bar.com' } }
wrapper.find('input').simulate('change', event)
t.true(onChange.calledWith(event))
})
这里用的shallow望文生义,也是向下渲染一层。此外我们还用了spy,这样测试就变得有点复杂了,丢掉了我们之前声明式的优雅,所以组件还是小一点、一下测完比较好。
还不够快?Facebook就觉得不够快,他们觉得View测试成本比较糜费,干脆搞了个Snapshot测试——意思就是照个像,只断言它不变。下次谁改了别的中央不小心影响到这里,就会挂掉,假设有意的就修好,假设有意的话和git一样commit一下就修好了:
import render from 'react-test-renderer'
test('Greeter', t => {
const tree = render.create(<Greeter name="React"/>).toJSON()
t.snapshot(tree, 'should not change')
})
当你修正Greeter的时分,测试就会挂掉,这时分运转:
ava --update-snapshots
就好了。Facebook自家的 Jest 对snapshot的支持更好,当snapshot不婚配时按个y/n就完事了,够快了吧。要有更快的能够就是不测了……
小结
这节里我们展现了3种测试View的不同方式,它们都比传统框架更复杂更快速。我们的思绪还是以判等为主,但不同于Model,粒度越大越好。View测试粒度越小越好,足够小、足够幂等之后,其实不用测试你也可以发现组件总是按照预期任务。相比之下MVVM自然有一种让View和Model粒度拟合的倾向,很容易让测试变得既难测又缺乏价值。
异步Effect测试
这算个续集……异步操作不复杂的项目可以无视这段,可以选择性不测。
React先处置了恶心的DOM成绩,把Model的成绩留下了。然后Redux把同步逻辑处置了,其实前端还留下异步操作的大成绩没有处置。这种相似“Unix只做一件事”的哲学是React全家桶的根基。我们用一个叫做 Redux-saga 的库来展现全家桶的异步测试怎样写,Redux模拟的目的是 Elm architecture,但是简化掉了Elm的作用模型,只保留了同步模型,Redux-saga其实就是把Elm的作用模型又拿回来了。
Saga是一种worker形式,很早之前在Java社区就存在了。Redux-saga笼统出来多种通用的作用比如call / takeEvery等等,然后有了这些作用,我们又可以愉快地判等了。比如:
import { takeEvery, put, call, fork, cancel } from 'redux-saga/effects'
function *account() {
yield call(takeEvery, 'login/REQUESTED', login)
}
function *login({ name, password }) {
try {
const { token } = yield call(fetch, '/login', { method: 'POST', body: { name, password } })
yield put({ type: 'login/SUCCEEDED', token })
}
catch (error) {
yield put ({ type: 'login/FAILED', error })
}
}
这段代码乍看起来很丑,这是由于它把顺序里一切异步操作全都集中在本人身上了。其他部分都可以开心肠发同步事情了,此外有了Saga之后Redux终于有了“用事情触发事情”的机制了,只用redux,运用复杂到一定水平你一定会想这个成绩的。
这是个最普通的API处置saga,一个account worker看到每个’login/REQUESTED’就会forward给login worker(takeEvery),让它继续管下面的事。然后login worker拿到音讯就会去发央求(call),之后傻傻地等着回复,或许是出错。最后它会收回和结果相关的事情。用这个方式你可以轻松处置疯狂难度的异步成绩。
test('account saga', t => {
const gen = account()
t.deepEqual(gen.next().value, call(takeEvery, 'login/REQUESTED', login))
})
test('login saga', t => {
(责任编辑:admin)