Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Branch Coverage for Redux reducer

Say I have the following reducer:

import {FOO} from '../const/Foo'

const myReducer = (initialState = {foo: ''}, action) => {
  const state = {}
  if (action) {
    switch (action.type) {
      case FOO:
        state.foo = action.foo
    };
  }
  return Object.assign({}, initialState, state)
}

and I test using jest with:

import FOO from '../const/Foo'

test('returns correct state when action is not "Foo"', () => {
  expect(myReducer({foo: 'bar'}, {type: 'foo'})).toEqual({foo: 'bar'})
})

test("returns correct state when action is 'Foo'", () => {
  expect(myReducer({}, {type: FOO, foo: 'bar'})).toEqual({foo: 'bar'})
})

test('when there is no action / testing the default', () => {
  expect(myReducer()).toEqual({foo: ''})
})

This produces a branch coverage of 4/5. After a little bit of thinking/removing and/or re-adding lines I've arrived at the branching logic being on the initialState set. Which almost makes sense. Except:

1) Why doesn't the last test, with an empty myReducer() call cover this case.

When the reducer is pared down to:

const myReducer = (initialState = {foo: ''}, action) => {
    const state = {}
    return Object.assign({}, initialState, state)
}

The tests (which now fail) have a branch coverage of 1/1.

What is going on here?

EDIT: As per request, I am adding the configuration. I pass the following jest.json to jest:

{

  "bail": true,
  "verbose": true,
  "moduleNameMapper": {
    "\\.(sass|jpg|png)$": "<rootDir>/src/main/js/config/emptyExport.js"
  },
  "testRegex": ".*(?<!snapshot)\\.(test|spec)\\.js$",
  "collectCoverage": true,
  "collectCoverageFrom": ["src/main/js/**/*.js"
    , "!**/node_modules/**"
    , "!**/*spec.js"
    , "!src/main/js/config/emptyExport.js"
    , "!**/coverage/**/*.js"
    , "!src/main/js/app.js"
    , "!src/main/js/store/configureStore.js"
    , "!src/main/js/reducers/index.js"],
  "coverageDirectory": "<rootDir>/src/main/js/coverage",
  "coverageThreshold": {
    "global": {
      "branches": 85,
      "function": 95,
      "lines": 95,
      "statements": 95
    }
  }
}

EDIT2: The following test also does not affect test coverage:

test('when there is no action / testing the default', () => {
  expect(addressReducer(undefined, {foo: 'bar'})).toEqual({address: ''})
})

I still do not understand why the initial default test implementation was not equivalent from a branch coverage perspective.

like image 796
Abraham P Avatar asked Feb 09 '17 12:02

Abraham P


People also ask

What is branch in jest coverage?

Branch coverage is a requirement that, for each branch in the program (e.g., if statements, loops), each branch have been executed at least once during testing. (It is sometimes also described as saying that each branch condition must have been true at least once and false at least once during testing.)

What are the parameters for a Redux Reducer?

State: The reducer function contains two parameters one of them is the state. The State is an object that holds some information that may change over the lifetime of the component. If the state of the object changes, the component has to re-render. In redux, Updation of state happens in the reducer function.

Why Redux Reducer is called reducer?

The reducer is a pure function that takes the previous state and an action, and returns the next state. (previousState, action) => newState. It's called a reducer because it's the type of function you would pass to Array.

What is action reducer in Redux?

Reducers, as the name suggests, take in two things: previous state and an action. Then they reduce it (read it return) to one entity: the new updated instance of state. So reducers are basically pure JS functions which take in the previous state and an action and return the newly updated state.


1 Answers

the last test with myReducer() covers the case where the default value for initialState which is in your case {foo: ''} gets applied.

like image 133
apoh Avatar answered Sep 29 '22 23:09

apoh