環境
$ npm list vue
app@1.0.0 \app
├─┬ @vue/test-utils@1.2.2
│ └── vue@2.6.14 deduped
├── vue@2.6.14
└─┬ vuex@3.6.2
└── vue@2.6.14 deduped
$ npm list mocha
app@1.0.0 \app
└── mocha@3.5.3
問題があるパターン
- DOM の構築後、もしくは更新後の状態を確認する為、
Wapper.vm.$nextTick
を用いて以下の用にテストコードを記述したとする。
test.spec.js
describe('Form', function () {
it('test', function (done) {
const wrapper = mount(LoginForm)
wrapper.vm.$nextTick(function () {
expect(true).to.equal(false) // AssertionError を発生させる
done() // done の call
})
})
})
-
npm run unit
実行してものログにはAssertionError
は表示されない - 代わりに 「done() が 呼ばれてないぞ」エラーになる
- これじゃテストにならない
log
Form
× test
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
解決策
- Mocha API をよく読むと、非同期でのテストについて、2パターンあると紹介されている
- done() コールバックを直接呼ぶ or Promiseを返却する
-
Wapper.vm.$nextTick
は、Vue.nextTick
と仕様が同じ。 - Vue.js APIを読むと、2.1.0 からは実行環境によるが Promise がサポートされるとのこと(ポリフィルは必要)
- 因みに、
vm.$nextTick()
を引数無しで call すると、Promise を返すようになる。(Gitのどっかで見た。公式APIにも記載あり。)
パターン1:AssertionError
をハンドルしdone()
にエラーオブジェクトを渡して call する
test.spec.js
describe('Form', function () {
it('test', function (done) {
const wrapper = mount(LoginForm)
wrapper.vm.$nextTick()
.then(function () {
expect(true).to.equal(false) // AssertionError
done()
})
.catch(err => done(err))
})
})
log
Form
× test
AssertionError: expected true to equal false
at webpack:///test/unit/specs/components/molecules/test.spec.js:nn:xxx <- index.js:nn:xxx
- アサーションエラーがハンドルされている。
- エラー行も表示されるのでテストが可能。
パターン2:Promise を返却する
test.spec.js
describe('Form', function () {
it('test', function () { // done を引数として受け取らない
const wrapper = mount(LoginForm)
return wrapper.vm.$nextTick()
.then(function () {
expect(true).to.equal(false) // AssertionError を発生させる
})
.catch(err => { throw err }) // エラーをキャッチして throw する。Error を内包した Promise が返却される
})
})
log
Form
× test
AssertionError: expected true to equal false
at webpack:///test/unit/specs/components/molecules/test.spec.js:nn:xxx <- index.js:nn:xxx
- アサーションエラーがハンドルされている。
- エラー行も表示されるのでテストが可能。
参考
以上