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

Allow file storage instead of forcing :memory: #26

Open
cyrille-gaucher opened this issue Mar 29, 2018 · 4 comments
Open

Allow file storage instead of forcing :memory: #26

cyrille-gaucher opened this issue Mar 29, 2018 · 4 comments

Comments

@cyrille-gaucher
Copy link

cyrille-gaucher commented Mar 29, 2018

Hi,

First of all, thank you for your work. Your lib is great!

It would be nice to allow the use of storage in file.

In my use case I have different connections all along the unit tests. When using the :memory: option, each connection seems to work with it's own allocated memory and so with its own DBs.

I'd like them to share the same DB and the only solution I see here is not to override the storage option.

The concerned code is located in the sequelize-mocking.js file in the adaptSequelizeOptions and a solution would be as follows:

const SQLITE_SEQUELIZE_OPTIONS = {
    'dialect': 'sqlite'
}
const SQLITE_SEQUELIZE_DEFAULT_OPTIONS = {
    'storage': ':memory:'
};

class SequelizeMocking {
    static adaptSequelizeOptions(sequelizeInstance, options) {
        let optionsExtended = _.merge(
            { },
            SQLITE_SEQUELIZE_DEFAULT_OPTIONS,
            sequelizeInstance.options,
            SQLITE_SEQUELIZE_OPTIONS,
            { 'logging': options && !options.logging ? false : console.log }
        );

        return optionsExtended;
    }
    ...
}

I hope I'm clear enough

@rochejul
Copy link
Owner

Hi

I am not sure to understand why we need this kind of option ? What are your expectations ?

I use in memory to reproduce the same behavior as HSQL when we made some unit tests on Java: to destroy and create quickly the whole database before each test, to be in a clean context.

I remember that we could share the context between tests, but this could be a bad practice (with side effects), because we are not sure of the context where the tests are running (we could use it if the database to reproduce is very big).

My point is: why is exactly your use case ? Because you say:

In my use case I have different connections all along the unit tests.

What does it mean ? You have some bugs ? Bad behaviors ? What is the issue or your expected issue?
Could you give a project sample to understand exactly your needs?

In all cases, even if I specified the "file mode", I think you will have the same "behavior", because I recreate a connection and flush the database. Maybe you could check it with "overriding" the code into the node_modules itself, to check what happens.

I think a sample project will be very usefull

Regards

@rochejul rochejul self-assigned this Mar 30, 2018
@cyrille-gaucher
Copy link
Author

Hi,

Thank you for taking time for my issue.

Sorry for my bad explanation. I'm not trying to have the same shared DB between my different unit tests. But I want my unit tests to share their DB with the code they are testing.

I'm trying to test an API.
The API is powered by ExpressJS framework.
The unit test opens its own connection to a SQLite database using a config file, and uses sequelize mocking to inject data into the DB.
When the unit tests run, chai starts a server for the API which has its own connection to a database through the same config file as above. When running in test env, the DB engine is SQLite.

The SQLite documentation says:

In-memory databases are allowed to use shared cache if they are opened using a URI filename. If the unadorned ":memory:" name is used to specify the in-memory database, then that database always has a private cache and is this only visible to the database connection that originally opened it

So in my case, the unit tests has opened its own connection to a SQLite DB and injected data in its own in-memory DB. When my unit tests run, the server is started with it's own connection to a SQLite DB. Therefore I'm not able to have shared data between both because of the :memory: option which is forced.

I hope that's more comprehensible now.

I'll try to setup a sample project but I don't have much time.

Thanks again for your time.

@rochejul
Copy link
Owner

rochejul commented Apr 3, 2018

@cyrille-gaucher Hi

Ok I think I see your issue.

In fact, if I understand, you setup your server with injecting some data. And with the current implementation of sequelize-mocking, the data are not well transfered?

Because I try to copy all already declared tables, models, ....
But I don't think I try to inject data injected from the server setup: I suppose the test-user will use the loadFixtures approach.

Maybe in your case, you could in a first case declare some JSON files and use the loadFixtures mechanism. See:

sequelizeMockingMocha(
        Database.getInstance(),
        path.resolve(path.join(__dirname, './fake-users-database.json')),
        /* Or load array of files
        [
            path.resolve(path.join(__dirname, './fake-users-database.json')),
            path.resolve(path.join(__dirname, './fake-candy-database.json')),
        ]
        */
        { 'logging': false }
    );

I could try to detect if we have injected some data before the mocking mechanism is enabled, but I think it will be quiet complex, and I don't know if this is a good idea (in my mind, database mocking tools are used to reproduce a full declared context, and play with it).

I try to make some investiguation on that way.

Many thanks for your feedback.

Regards

PS: if you could provide a tiny example, I will use it to try to put in place this strategy.

@cyrille-gaucher
Copy link
Author

cyrille-gaucher commented Apr 3, 2018

Hi @rochejul ,
I've quickly set up a project to expose my issue. You will find it here : https://github.com/cyrille-gaucher/seq-mocking-example

I hope it's gonna be more understandable.

The issue is more located on having two different connections:

  • One instantiated in the tested code (the server)
  • One instantiated in the testing code (the unit test)

Each connection has its own memory space allocated. SQLite won't share any data between connection.

When you will run unit tests, the second one is going to fail. That's exactly the problem I'm facing in my real project.

I'm aware the architecture of the sample project may appear a bit weird. It is just showing what is strictly necessary to understand the issue, but this architecture (which is much more complex and correctly factorised) is necessary in my real project.

Let me know if anything is not working as expected.

Thank you again for helping

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

No branches or pull requests

2 participants