Mock a database function for unit testing - c#

I'm trying to make unit tests for a query. Inside this query I call an database function. This function is a CTE (Common-Table-Expression). For testing purposes I want to mock this CTE.
My question is, how am I mocking this database function in entity-framework-core?

Long story short - You can't. You can only mock function C# related data.
Testing code that uses EF Core
It is very important to understand that EF Core is not designed to abstract every aspect of the underlying database system. Instead, EF Core is a common set of patterns and concepts that can be used with any database system.
BUT - Depending on the type of tests you are doing:
Running queries and updates against the same database system used in production.
Running queries and updates against some other easier to manage database system.
Using test doubles or some other mechanism to avoid using a database at all.
You could setup the data (1 or 2 - for the 3rd one it's irrelevant), so that your function returns the proper data. You can always do that on for the 1st choice, but not always for the 2nd (as the easier to manage database, will not always support the same functions).
Maybe with some code and a bit more context, we can help more.

Related

How to unit test the saving of a collection

I am trying to write a unit test for a method that saves multiple records into a database. The method is passed a collection argument. The method loops through the collection. The userid associated with the object is set and the record is updated in the the database. This is done for every object in the collection. Any idea on how to create a unit test besides having it write to the database.
Thanks,
As mentioned in comments, you have an option to abstract the database operations by some interface. If you use ORM, you can implement generic repositories, if you use plain ADO.NET, you can implement something like transaction script.
Another option would be to use SQLite in-memory database. It is not clear what db interface you are using, but SQLite is supported by the majority of database access methods in .NET, including Entity Framework. This would not exactly be a unit test but it does the job.
As has been suggested in the comments, you have 2 choices
Create an abstraction for the actual writing to the database and verify the interactions with that abstraction are as you would expect for your method. This will give you fast unit tests but you will still have to write integration tests for the implementation of your abstraction which actually puts data in the database. To verify the interactions you can either use a mocking library or create an implementation of the interface just for testing with.
Create an integration test that writes to the database and verify that the data is inserted as you would expect. these tests will be slower, but will give you confidence that the data will actually be placed in the database.
My preference is for the second option, as this tests that the data will actually be persisted correctly, something you are going to have to do eventually, but not everyone likes to do this.

Any Automocking frameworks that generate from actual data in database

Does anything described below exist?
Hi, I'm a c# and javascript programmer. When creating tests the pain point for me is the creation of the test dependencies. Especially when I am making assertions against values that I expect in the database.
I know that writing tests that make calls to the database is a bad practice since many database calls can slow down the entire test suite. The alternative is we as developers must create these large sometimes complicated mock objects that contain the values that the database would otherwise be returning.
Instead I would like to create my tests against an actual database. Then I would like for my test running application or testing framework to make note of the object returned from the database. The testing framework would replace the dependency on the database with an automatically created stub object for all subsequent runs of this test.
Essentially the database would only get hit the very first time a test is run and from that point forward it would instead use that data it retrieved from the first pass of the test as the stub or mock object.
This would entirely mitigate the need to ever manually create an object for the purpose of testing.
You could use AutoFixture to create the data.
It does have some support for data annotations, but you'd probably still need to tweak it extensively to fit your particular database schema.

How to seed database data for integration testing in C#?

I've been writing some integration tests recently against ASP.Net MVC controller actions and have been frustrated by the difficulty in setting up the test data that needs to be present in order to run the test.
For example, I want to test the "add", "edit" and "delete" actions of a controller. I can write the "add" test fine, but then find that to write the "edit" test I was am either going to have to call the code of the "add" test to create a record so that I can edit it, or do a lot of setup in the test class, neither of which are particularly appealing.
Ideally I want to use or develop an integration test framework to make it easier to add seed data in a reusable way for integration tests so that the arrange aspect of an arrange/act/assert test can focus on arranging what I specifically need to arrange for my test rather than concerning itself with arranging a load of reference data only indirectly related to the code under the test.
I happen to be using NHibernate but I believe any data seeding functionality should be oblivious to that and be able to manipulate the database directly; the ORM may change, but I will allways be using a SQL database.
I'm using NUnit so envisage hooking into the test/testfixture setup/teardown (but I think a good solution would potentially transferable to other test frameworks).
I'm using FluentMigrator in my main project to manage schema and seeding of reference data so it would be nice, but not essential to be able to use the FluentMigrator framework for a consistent approach across the solution.
So my question is, "How do you seed your database data for integration testing in C#?" Do you execute the SQL directly? Do you use a framework?
You can make your integration testing on Sql Server Compact, you will have a .sdf file and you can connect to it giving the file's path as connection string. That would be faster and easier to setup and work with.
Your integration test would not probably need millions of rows of data. You can insert your test data into your database and save it as TestDbOriginal.sdf.
When you are running your tests, just make a copy of this 'TestDbOriginal.sdf' and work on that copy, which is already seeded with data. If you want to test a specific scenario, you will need to prepare your data by calling some methods like add, remove, edit .
When you go production or performance testing, switch back to your original server version, be it Sql Server 2008 or whatever.
I don't know if it's necessarily the 'right' thing to do, but I've always seeded using my add/create method(s).

How to unit test Entity Framework?

I'm trying to test my code using EntityFramework code first. In order to make it testable and to allow isolation testing, I created an interface which my DbContext implements. I'm not testing the DbContext class - I'm going to assume EF code works as expected.
Now, consider the following method:
public IEnumerable<User> GetOddId()
{
return context_.Users.Where((u, i) => i % 2 == 1).AsEnumerable();
}
This method will pass with my mock FakeDbSet (because it would use the in-memory LINQ provider) whereas it would fail with an Exception when using the EF/LINQ to SQL drivers.
Would you leave it as it is and hope people know enough not to write such queries? Would you give up isolation testing and test on an actual db?
Would the LocalDb with DataMigrations (perhaps with appropriate seeds) help with testing on an actual db?
Please justify the answer(s).
TLDR: How to test EntityFramework code, considering the differences between in-memory LINQ and SQL LINQ?
Much later edit: I've since found a very good framework that does exactly what I need. I wrote a blog post about unit testing with Effort. Also please note all this might not be needed in the upcoming EF6, which promises a some unit testing features.
We use SQLite's in-memory databases for this purpose. They are extremely quick to create, query and tear down and barely have any impact on overall test speed. Once you've set yourself up a test framework to create a database and inject data, tests are quick to write.
Of course, SQLite is a much simpler database than most, so complex queries may fail to translate to its version of SQL, but for testing 90% of cases, it works well.
Do these tests constitute integration tests? I don't think so. They are still only testing one unit of your code, namely the bit that generates a LINQ query. You're testing for two things: 1) that the query returns the correct data (but you could check this using an in-memory collection as you stated), and 2) that the query can be translated into valid SQL by Entity Framework. The only real way to test the latter is to fire the query at a real Entity Framework but with a stubbed database.
Whilst you could argue that a true unit test should test just the output of your code (i.e. parse and check the expression tree that has been generated), as well as being harder to write, it doesn't really prove anything. If, for example, you modify the code to generate an inner join instead of a subquery, would you want the test to break? Only if it returns different results, I would have thought.
Where I work, we have a dev/beta/production SQL server. Sometimes we'll create tests against beta and seed test data (e.g. insert before testing specific selects and such) before executing tests on an actual database. People will draw a distinction between unit and integration testing, but it at least lets us test our logic, which is better than just crossing fingers and hoping for the best at the data-access layer.
What good is an in-memory provider that's easy to test for but doesn't actually represent the live system in some important cases?
EDIT: We don't use EF, btw...
You might want to use a mocking framework like Telerik's JustMock (or choose from many others).
This would give you lots of control over what happens in your test code. (Short introduction here.)
Instead of implementing a query to a real database you could 'simulate' the query and return a pre-defined collection of objects.
You could, for example, create multiple unit tests that call your GetOddId() method, and define different return collections that cover all the test cases you need (an empty list, correct content, wrong contents, throwing an exception, whatever, ...).
There is also a free 'Lite' version here or via NuGet.

Mocking ISession.Query<T>() for testing consumer

I'm trying to avoid using an in memory database for testing (though I might have to do this if the following is impossible). I'm using NHibernate 3.0 with LINQ. I'd like to be able to mock session.Query<T>() to return some dummy values but I can't since it's an extension method and these are pretty much impossible to test.
Does anyone have any suggestions (other than using an in memory database) for testing session queries with LINQ?
I've tried this before with previous versions of NH without much luck. I eventually used another class to wrap the query and mocked that instead.
I do think it's also worth writing an integration test against a real sql server, to make sure that the repository behaves as expected.
A better approach will be to mock the concept of what you are trying to do, not the inner api of an external system.
For instance
Write the query in a separated artifact, like IQuerySomething / QuerySomething
Test your query against a database. Try this database be prety like the real db.
When testing something that depends on IQuerySomething, mock IQuerySomething.
Fabio Maulo wrote about this pattern as EQO (Enhanced Query Object), i recommend you his post.
This is the way we use in .net for almost everything.
It's looking like you are going to overcomplicate things. I will try to save your time =)
First of all let's start that there is two tipes of testing for the typical project (I am sure you know this, but it is better to mention). Integration tests and Unit tests. And typically (I will assume that you have a typicall application in order no to add "typically" to every sentence) you need both of them.
Integration tests are going on real database and some of them on In-Memory one for better test performance.
So you probably have mappings in your application and want to test them, it is better to do with integration tests on real DB, and if you are using Fluent Nhibernate (if you don't it is better to start using it) this will be a pice of cake.
Then you probably have a kind of Repository or another data access layer (where you are using Linq) that you want to test too. And you probably want to have tests like:
When I submit a query get-customer-by-name, my data access component should return customer with specified name.
This is better to achieve using in-memory database, because this is cheaper. This will save you some time in the typical scenario.
But if you have a lot of complex queries, then I would agree with José F. Romaniello, that it is better to use Enhanced Query Object and test it separately.
You can put your attention on Sharp Arhitecture framework that is targeting a lot of issues when using Nhibernate and testing persistence layer.

Categories

Resources