2017-03-06 35 views
7

为了让我的传奇文件100%覆盖,我正在研究如何测试观察者。单元测试REDX-SAGA的观察者有什么意义?

我一直在google搜索,关于如何测试观察者有几个答案。也就是说,做一个takeEverytakeLatest的传奇。

但是,所有的测试方法似乎基本上复制实现。那么,如果测试结果相同,那么编写测试有什么意义呢?

例子:

// saga.js 

import { delay } from 'redux-saga' 
import { takeEvery, call, put } from 'redux-saga/effects' 
import { FETCH_RESULTS, FETCH_COMPLETE } from './actions' 

import mockResults from './tests/results.mock' 

export function* fetchResults() { 
    yield call(delay, 1000) 
    yield put({ type: FETCH_COMPLETE, mockResults }) 
} 

export function* watchFetchResults() { 
    yield takeEvery(FETCH_RESULTS, fetchResults) 
} 

试验方法1:

import { takeEvery } from 'redux-saga/effects' 
import { watchFetchResults, fetchResults } from '../sagas' 
import { FETCH_RESULTS } from '../actions' 

describe('watchFetchResults()',() => { 
    const gen = watchFetchResults() 
    // exactly the same as implementation 
    const expected = takeEvery(FETCH_RESULTS, fetchResults) 
    const actual = gen.next().value 

    it('Should fire on FETCH_RESULTS',() => { 
     expect(actual).toEqual(expected) 
    }) 
    }) 

试验方法2:用一个帮手,像Redux Saga Test Plan
这是写作的方式不同,但我们再做一次基本相同作为实施。

import testSaga from 'redux-saga-test-plan' 
import { watchFetchResults, fetchResults } from '../sagas' 
import { FETCH_RESULTS } from '../actions' 

it('fire on FETCH_RESULTS',() => { 
    testSaga(watchFetchResults) 
    .next() 
    .takeEvery(FETCH_RESULTS, fetchResults) 
    .finish() 
    .isDone() 
}) 

相反,我想简单地知道,如果watchFestchResults采取一切FETCH_RESULTS。或者甚至只有在它发生火灾takeEvery()。不管它如何跟进。

或者这真的是这样做吗?

+0

佐贺

import { takeLatest, call, put } from 'redux-saga/effects'; import { actions, types } from 'modules/review/reducer'; import * as api from 'api'; export function* requestReviews({ locale }) { const uri = '/reviews?filter[where][locale]=${locale}'; const response = yield call(api.get, uri); yield put(actions.receiveReviews(locale, response.data[0].services)); } // Saga Helper export default function* watchRequestReviews() { yield takeLatest(types.REVIEWS_REQUEST, requestReviews); } 

测试例子是啊,我被这个困惑了。示例测试都将结果与传奇效果创作者进行比较。这不是我关心的。我关心他们是否把商店置于正确的状态。这些例子的测试看起来非常脆弱,没有任何证据。 –

回答

4

这听起来像测试他们的目的是要实现100%的测试覆盖率。

有些事情你可以单元测试,但是如果你应该这样做的话,这是值得怀疑的。

在我看来,这种情况可能是“整合”测试的更好选择。一些不仅仅测试单一方法,而是几种方法作为一个整体一起工作的东西。也许你可以调用一个动作来触发一个使用你的传奇的减速器,然后检查商店的结果变化?这比单独测试这个传奇更有意义。

2

我同意约翰迈尔的answer,这是更适合集成测试比单元测试。这个issue是GitHub中最受欢迎的选票。我会建议阅读它。

其中一个建议是使用redux-saga-tester打包问题的开启者创建。它有助于创建初始状态,启动传奇帮手(takeEvery,takeLatest),分派传奇正在倾听的动作,观察状态,检索动作历史记录以及侦听发生的特定动作。

我使用它与axios-mock-adapter,但在代码库中使用nock有几个示例。用玩笑

import { takeLatest } from 'redux-saga/effects'; 
import { types } from 'modules/review/reducer'; 
import SagaTester from 'redux-saga-tester'; 
import MockAdapter from 'axios-mock-adapter'; 
import axios from 'axios'; 

import watchRequestReviews, { requestReviews } from '../reviews'; 

const mockAxios = new MockAdapter(axios); 

describe('(Saga) Reviews',() => { 
    afterEach(() => { 
    mockAxios.reset(); 
    }); 

    it('should received reviews', async() => { 
    const services = [ 
     { 
     title: 'Title', 
     description: 'Description', 
     }, 
    ]; 
    const responseData = [{ 
     id: '595bdb2204b1aa3a7b737165', 
     services, 
    }]; 

    mockAxios.onGet('/api/reviews?filter[where][locale]=en').reply(200, responseData); 

    // Start up the saga tester 
    const sagaTester = new SagaTester({ initialState: { reviews: [] } }); 

    sagaTester.start(watchRequestReviews); 

    // Dispatch the event to start the saga 
    sagaTester.dispatch({ type: types.REVIEWS_REQUEST, locale: 'en' }); 

    // Hook into the success action 
    await sagaTester.waitFor(types.REVIEWS_RECEIVE); 

    expect(sagaTester.getLatestCalledAction()).toEqual({ 
     type: types.REVIEWS_RECEIVE, 
     payload: { en: services }, 
    }); 
    }); 
}); 
相关问题