Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sequelize-typescript with jest.js tests #688

Closed
grzegorzCieslik95 opened this issue Oct 8, 2019 · 11 comments
Closed

Sequelize-typescript with jest.js tests #688

grzegorzCieslik95 opened this issue Oct 8, 2019 · 11 comments

Comments

@grzegorzCieslik95
Copy link

grzegorzCieslik95 commented Oct 8, 2019

Versions

  • sequelize: 5.19.2
  • sequelize-typescript: 1.0.0
  • typescript: 3.6.3

I'm submitting a ...

[ ] bug report
[X] feature request

Hi,
Do you have any idea, how should I mock Sequalize class in tests in this case?

I have repository

const mockGetRepository = {
    findOne: jest.fn(),
};
import User from 'models/User';

jest.mock('components/DatabaseConnection', () => {
    return {
        __esModule: true,
        default: {
            addModels: (m: any) => {
                return;
            },
            getRepository: () => mockGetRepository,
            models: {User},
        },
    };
});

import models from 'models';
import UserRepository from 'repositories/UserRepository';

describe('UserRepository test', () => {
    it('findById test - user exist', async (done) => {
        mockGetRepository.findOne.mockImplementationOnce(() => {
            return new models.User({id: 123});
        });

        const user = await UserRepository.findById(123);
        expect(user).toEqual({id: 123});
        done();
    });
});

When I try to create a new instance of User I got an error like that

 Model not initialized: User cannot be instantiated. "User" needs to be added to a Sequelize instance.

Do you have any idea, how can I fix this problem?

@RobinBuschmann
Copy link
Member

Hey @grzegorzCieslik95 thanks for bringing this up! You could create another sequelize instance just for testing purposes with option validateOnly: true:

new Sequelize({
  validateOnly: true,
  models: [__dirname + '/models'] // don't forget to add your models like this... or [User, ...]
});

With validateOnly sequelize doesn't connect to any database, but the models get initialized and can be instantiated.

Hope this helps!

Maybe it would be better to provide an option, which is exclusively defined for testing purposes like testMode: true 🤔

@grzegorzCieslik95
Copy link
Author

grzegorzCieslik95 commented Oct 18, 2019

Hi @RobinBuschmann !
Thanks for your answer. In my project, I changed ORM to typeorm, but in the future project, I will try to use sequelize again.
If sequelize with validateOnly doesn't connect to the database, I think the better name is shouldConnectToDatabase or something similar. And if you can add a better description for this key will be great, because now description If true enable validate only mode nothing tell to us IMHO.

Have a nice day :)

@RobinBuschmann
Copy link
Member

Closing this due to inactivity

@samosaboy
Copy link

Running into this same issue, using ts-jest as a preprocessor. I've tried with validateOnly flag but that does not work either.

@EdByrnee
Copy link

Running into this same issue, using ts-jest as a preprocessor. I've tried with validateOnly flag but that does not work either.

Did you manage to resolve this, can't find a solution anywhere?

@dante07577
Copy link

Running into this same issue, using ts-jest as a preprocessor. I've tried with validateOnly flag but that does not work either.

Did you manage to resolve this, can't find a solution anywhere?

Hi,
I have few words, maybe something will be useful for you:

  1. If your error is something like 'Model not initialized: User cannot be instantiated. "User" needs to be added to a Sequelize instance.' you can try to init object like this { foo:1, bar:'hello' } as User. In this case you will not be forced to add model to the Sequelize instance. That's means that you can simply mock Sequelize in the same way as regular service (jest.fn()) instead of initialize it
  2. If first one is not your way, i had no issues with validateOnly. The only thing that i have found annoying that if you forget to mock something (let say we added User.findAll call inside tested service method and didn't mock it) then it will try to connected to db and you will see some thing like 'database cannot be initialize' or error message similar to this one. So you just has to find these forgotten calls and mock them

I hope it will help you with your issue

@yatin166
Copy link

Hello,

I've tried the first solution with setting validateOnly: true and initialising all my Database Models, and I've got this error:
this.lib.Database is not a constructor
second option really seems very annoying since there can be LOT OF database calls happening in a test and all of those need to be mocked.
Please can you help @RobinBuschmann

@yatin166
Copy link

yatin166 commented Jun 3, 2021

I solved this issue by creating a mock/fake sequelize object with sqlite3 package as dialect property and validateOnly: true, you can give any fake database name and yet you can initialize all the models in model property.

new Sequelize({
        database: '<any name>',
        dialect: 'sqlite' as const,
        username: 'root',
        password: '',
        validateOnly: true,
        models: [__dirname + '/models'],
}); 

@pandrews-hdai
Copy link

pandrews-hdai commented Jul 1, 2021

@yatin166 As far as I can see validateOnly: true overrides whatever dialect was specified and forces some sort of 'dummy-db' version of sqlite dialect, see: https://github.com/RobinBuschmann/sequelize-typescript/blob/master/src/sequelize/sequelize/sequelize-service.ts#L27

If that's correct any dialect/database/username/password specified alongside validateOnly doesn't matter. I still seem to have the this.lib.Database is not a constructor error, but it seems to be coming directly from sequelize code in node-module, not the ConnectionManager that new Sequelize as imported from sequelize-typescript. I'd been trying to mock the models themselves with sequelize-mock and it sort of make me wonder if they're just mutually exclusive frameworks because they both wrap sequelize internals?

@gusparr28
Copy link

new Sequelize({
database: '',
dialect: 'sqlite' as const,
username: 'root',
password: '',
validateOnly: true,
models: [__dirname + '/models'],
});

A lot of time has passed. Were you able to solve it? I'm currently facing this exact same issue. I'm trying to pass to a Service Class a fake Sequelize instance to use transactions and been a lot of time struggling with it.

@pandrews-hdai
Copy link

@gusparr28 I don't know about anyone else but unfortunately I wasn't able to get anything to work with mocking models.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants