api-example icon indicating copy to clipboard operation
api-example copied to clipboard

Mocking the UserService auth() function in "auth failure" test from \controllers\__tests__\user_failure.ts

Open abrasat opened this issue 4 years ago • 4 comments

First of all many thanks for the very useful articles and for the code repository! I have problems mocking the methods from "\services\user.ts" If executing "auth failure" as in the code from the github repository the following error occurs:

TypeError: user_1.UserService_auth.mockRejectedValue is not a function

To get rid of this error I changed then the "\controllers_tests_\user_failure.ts" code to:

jest.mock("@exempl/api/services/user", () => ({
  UserService_auth: jest.fn(() => Promise.reject(new Error())),
  UserService_login: jest.fn(() => Promise.resolve({error: {type: 'unkonwn'}})),
  UserService_createUser: jest.fn(() => Promise.resolve({error: {type: 'unkonwn'}})),
}));

The test looks like this now (I removed the line "(UserService.auth as jest.Mock).mockRejectedValue(new Error())" before calling "request(server)"):

describe('auth failure', () => {
  it('should return 500 & valid response if auth rejects with an error', async done => {
      request(server)
      .get(`/api/v1/goodbye`)
      .set('Authorization', 'Bearer fakeToken')
      .expect(500)
      .end(function(err, res) {
        if (err) return done(err)
        expect(res.body).toMatchObject({error: {type: 'internal_server_error', message: 'Internal Server Error'}})
        done()
      })

I replaced also the default export in"\services\user.ts" with several named exports:

...
//export default {auth: auth, createAuthToken: createAuthToken, login: login, createUser: createUser}
export const UserService_auth = auth;
export const UserService_createAuthToken = createAuthToken;
export const UserService_login = login;
export const UserService_createUser = createUser;

The test result is now:

expected 500 "Internal Server Error", got 401 "Unauthorized"

Obviously it still calls the "original" auth() function instead of the mocked one and I dont know why, maybe you can help me with some advice. I am testing on Windows 10.

abrasat avatar Feb 22 '21 16:02 abrasat

@abrasat, remove "bin" folder from the root. Please let me know if it still doesn't work.

losikov avatar Feb 22 '21 17:02 losikov

Yes, it worked (my output folder is actually /dist), thank you very much! I tested my last version with several named exports instead of the default export, but I guess your original code will work too (I will check it tomorrow). I had found some articles recommending not to use the default export in typescript and I thought first that that might be the problem. But back to the problem: why did I have to delete the output directory ? Does jest not recompile everything? Or is there a way to "force" the recompile of all files? Later edit: Could you please explain how ts-jest works? Does it compile ts code to js at all? Do I have to remove each time the output files generated by "yarn build" before performing the tests with "yarn test:unit"?

abrasat avatar Feb 22 '21 19:02 abrasat

@abrasat ts-jest executes ts files on fly (compiling to js in-memory, not to disk). It fails because it uses js files in bin folder, not ts files in src folder. It is the reason of the failure. Let me know if you find a solution to fix it (force ts-jest to look at src first, not bin).

losikov avatar Feb 24 '21 15:02 losikov

@losikov Adding the following setting into jest-config.js makes ts-jest ignore the *.js files, it solved the problem for me

testPathIgnorePatterns: [".d.ts", ".js"]

Found the solution here: https://stackoverflow.com/questions/50145078/jest-typescript-tests-runs-twice-one-for-ts-files-and-one-for-js-files

abrasat avatar Feb 25 '21 11:02 abrasat