2

If I have code something like this:

import externalThing from 'externalThing'
import anotherThing from 'anotherThing'

function functionIWantToTest()
{    
    externalThing.doSomething()
    .then(data=>{
        anotherThing.do(data.Id)
    })
}

What is the best practice way to unit test this?

Ideally the test would be something like this:

import externalThing from 'externalThing'
import anotherThing from 'anotherThing'

jest.mock('externalThing',()=>jest.fn())
jest.mock('anotherThing',()=>jest.fn())

describe('when calling functionIWantToTest',()=>{

    beforeEach(()=>{     
       anotherThing.do=jest.fn()
       //mock external thing somehow so that it still the 'then' code

       functionIWantToTest()
    })

    it('anotherThing should be called',()=>{
        expect(anotherThing.do).toHaveBeenCalledWith(1)
    });
});

But when I try I just end up building a chain of mocked functions with jest.fn() and no code actually gets executed.

Dan
  • 29,100
  • 43
  • 148
  • 207
  • What is expected result of `functionIWantToTest()` call? – guest271314 Aug 13 '17 at 18:56
  • Hey @guest271314 its in the test :), for `anotherThing.do` to have been called with a param. – Dan Aug 13 '17 at 19:07
  • Have not tried `jest`. What does `jest.fn()` return? Are there two different assignments of values to `anotherThing.do`? Note that no values are actually returned from `functionIWantToTest()` call – guest271314 Aug 13 '17 at 19:10
  • `jest.fn()` returns a mocked function, you can provide mock implementation by doing `jest.fn(()=>{...} )`. Yeah its a void function, I am expecting it do call something else(there is more logic in the real code) – Dan Aug 13 '17 at 19:13
  • Ok. Though still no value is returned from `functionIWantToTest()` call. Why do you `anotherThing.do=jest.fn()` if `anotherThing` is a function that is already defined at `import anotherThing from 'anotherThing'`? – guest271314 Aug 13 '17 at 19:15
  • Because its a unit test, I am mocking everything that is not part of the current unit? – Dan Aug 13 '17 at 19:16
  • Yes, though your unit tests do not return any values. Again, am not familiar with `jest`. Would expect a function call which is being tested to return a value. Is a value not expected to be returned from either function? – guest271314 Aug 13 '17 at 19:17
  • Does it need too? I am expecting with `.toHaveBeenCalledWith` – Dan Aug 13 '17 at 19:19
  • Not sure what you are expecting. Should `jest.fn()` be `jest.fn` to reference the function? Are you just trying to determine if `1` is the parameter passed to `anotherThing.do()` call? – guest271314 Aug 13 '17 at 19:20
  • I want to test, when I call `functionIWantToTest`, subsequently `do(someThingFromAsyncCall)` happens – Dan Aug 13 '17 at 19:27

1 Answers1

1

Have not tried jest. You can use console.assert() to test the function calls and Promise values returned. Note, no value is actually returned from either of the function calls, if that matter to the expected result, see Why is value undefined at .then() chained to Promise?.

function functionIWantToTest() {
  return Promise.resolve({
      Id: 1
    })
    .then(data => {
      console.assert(data.Id === 1, data, [`${data.Id} is not equal to 1`]);
      console.assert(data.Id !== 1, data, [`${data.Id} is equal to 1`]);
    })
}

functionIWantToTest()
guest271314
  • 1
  • 15
  • 104
  • 177