admin管理员组

文章数量:1336331

I have function want to do unit testing, for example, it contains:

function foo (file, option) {
    return new Promise((resolve, reject) => fs.readFile(file, option, (err, content) => {
        if (err) return reject(new Error(`Failed to read the file: (${file})`));
        else {
            (...some operations, and that is the point for me to test it...)
            return resolve(...some result...);
        }
    }));
}

Just right at the beginning of the testing file, I have:

jest.mock('fs', () => ({
    readFile : jest.fn(),
}));
const fs = require('fs');

The testing logic is something like:

test('Should get context as string from the template file', async () => {
    const mockContent = '<a>Hello World</a>';
    fs.readFile.mockReturnValue(mockContent);
    const result = (await foo('test', 'utf8')).then(() => 123);
    //
    expect(result).toEqual(123);
});

However, when I try to run the test, it shows:

- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.`

I know it is an issue due to unresolved promise from Jest website; but their suggestion is not what I have actually... I recognize my problem is due to fs.readFile(...) is replaced by the mocking function which returns undefined so that the new Promise is never being rejected/resolved (am I correct?!).

My question is how can I do a unit test like this case? I really don't want to fire a I/O event like using a empty file in oder to make it work... Any thoughts?! Thanks!

/// UPDATE: I think a much clear question is how are we mock the data that received by a callback function. In my example it looks like I test against it, but in my real code, what I really want to test is the logic of the callback function.

I have function want to do unit testing, for example, it contains:

function foo (file, option) {
    return new Promise((resolve, reject) => fs.readFile(file, option, (err, content) => {
        if (err) return reject(new Error(`Failed to read the file: (${file})`));
        else {
            (...some operations, and that is the point for me to test it...)
            return resolve(...some result...);
        }
    }));
}

Just right at the beginning of the testing file, I have:

jest.mock('fs', () => ({
    readFile : jest.fn(),
}));
const fs = require('fs');

The testing logic is something like:

test('Should get context as string from the template file', async () => {
    const mockContent = '<a>Hello World</a>';
    fs.readFile.mockReturnValue(mockContent);
    const result = (await foo('test', 'utf8')).then(() => 123);
    //
    expect(result).toEqual(123);
});

However, when I try to run the test, it shows:

- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.`

I know it is an issue due to unresolved promise from Jest website; but their suggestion is not what I have actually... I recognize my problem is due to fs.readFile(...) is replaced by the mocking function which returns undefined so that the new Promise is never being rejected/resolved (am I correct?!).

My question is how can I do a unit test like this case? I really don't want to fire a I/O event like using a empty file in oder to make it work... Any thoughts?! Thanks!

/// UPDATE: I think a much clear question is how are we mock the data that received by a callback function. In my example it looks like I test against it, but in my real code, what I really want to test is the logic of the callback function.

Share Improve this question edited Jan 29, 2018 at 23:13 Leo Li asked Jan 29, 2018 at 0:57 Leo LiLeo Li 2574 silver badges20 bronze badges 3
  • The thing is that if you re testing against fs.readFileAsync you should not mock itself. Instead test it with fixture files directly for unit test. – Allen Commented Jan 29, 2018 at 1:47
  • And working with async functions you need to return a promise or invoke a callback passed from test(xxx, (done)). Btw your mocked jest.fn was not async at all – Allen Commented Jan 29, 2018 at 1:52
  • Thank you for pointing me out my mocked async function is not async at all! – Leo Li Commented Jan 29, 2018 at 2:20
Add a ment  | 

1 Answer 1

Reset to default 8

The problem, is the way you mock js.readFile. mockReturnValue just creates a function that returns something, but you want it to call on of its parameter so you need to use mockImplementation to define the mock function by yourself

jest.fn().mockImplementation((file, option, cb) => cb(null, mockContent)) 

or

jest.fn().mockImplementation((file, option, cb) => cb('Some Error', null))

本文标签: