1

This question is NOT about what's here: https://stackoverflow.com/questions/25960192/mocking-ef-dbcontext-with-moq and/or similar questions. I am well aware of that. Please, read the question before replying. Thanks.

  1. We have a fairly complicated database, which has some, call them, "business objects" (transactional data) and some, call them, "data objects" (operational data). The "business objects" are usually created or updated with every new user request and the "data objects" are fairly stable but may be occasionally created during user request if missing at the first call.

  2. I want to create integration tests in the sand box where I could pull the data objects out of the real database (because there are too many of them to mock) but control what happens with the business objects. For example, if I have a get or create workflow (with some validation, of course), then I want explicitly test that whole workflow after testing separately get or create workflows in some other tests. However, if I test get or create workflow, then with the real DB I can only test create part of workflow once but then I will only hit a get workflow (because the object will exist after the first test run). Throw in that many tests are routinely run in parallel and the results become unpredictable.

I wonder what is the proper approach to perform a partial "mock" of a database context where most of the tables would come from the real DB but a few tables could be setup per test, e.g. in InMemoryDbSets.

12
  • Would it be possible to have two databases, one with data objects and the other with business objects? The production code would just happen to use the same connection string for both databases. Mar 22, 2019 at 11:28
  • In theory yes, but in practice no :( . All the the databases have been already designed and went live a while ago. So now we have that DB with some business (transactional) objects and some data (operational) objects. That's why I have this question. Mar 22, 2019 at 11:54
  • Why not just copy the live database and do your sandbox testing in the copy? Mar 22, 2019 at 11:57
  • @KonstantinKonstantinov, what I meant is that the software treats the data as if it resides in two different databases. This should be possible if you don't need to make joins between tables with business objects and tables with data objects. That it is actually deployed as a single DB is then irrelevant. Mar 22, 2019 at 12:34
  • 1
    You also might want to look into creating real Unit Tests that can be run simultaneously without touching the DB at all. If you're using them I'm not sure how you ended up with 5000+ integration tests. Seems a bit much. Mar 22, 2019 at 14:34

1 Answer 1

1

The most practical method I have seen is to use database snapshots to create and revert a real database.

here is an article on the subject:

https://weblogs.sqlteam.com/mladenp/2007/07/06/60250/

Setup your database for the test or a set of tests and store the snapshot. Before running the tests use the snapshot to create the DB. When they care complete you can delete or revert the database as required.

You do not want to try to mock entity framework objects. For most purposes you should create a repository layer and mock that. But it sounds like this would be too much refactoring for you.

I note your comments on the size of the DB. Ideally you want to make your snapshot contain only the data needed for a single test. But you will have to judge the effort involved between manually setting up many small versions of the DB for each test vs larger 'copied from live' versions that can be used for large blocks of tests

3
  • Yeah. That's a good idea but I doubt that it would fly in our case :( . We run these 5k+ integration tests in parallel because otherwise they will take forever. If all of them are run in parallel, then they "want" to consume up to 30 GB of RAM for tests and additional about 10 GB of RAM for SQL, while having 1K+ simultaneous SQL connections. I have serious doubts that rolling back snapshots will work in this scenario. I have an idea, which is not as perfect as rolling back a snapshot, but it might still allow creating a near sand box experience. If it works, I will post it here. Mar 24, 2019 at 18:17
  • ... addressing your main comment: yes, unfortunately refactoring the db / repo layer is beyond my control and without that the idea of mocking the repo simply won't work. Throw in that transactional data are interwoven with operational data and that all :( Mar 24, 2019 at 18:23
  • Hmm it sounds like you have a very intense testing setup. If they literally need that much data to run, there's no getting around it regardless of what mocking you do. Maybe try splitting them over several machines?
    – Ewan
    Mar 24, 2019 at 22:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.