Mocking calls to SQL Server Stored Procedures? - c#

I am implementing an interface into a C# class, whose entire job is basically just to call some T-SQL stored procedures and return the data. Other implementations of the interface may obtain data through web-services, reading files, etc, so to test this particular class I'd ideally mock an SQL Server database and its procedures.
I'm not sure if this is feasible. I've seen tools like RhinoMock used to mock database tables but since the entire purpose of my code is to talk to a DB, can I mock the entire DB or is that a bit of a waste of time? I'd ideally like a way to transparently provide a replacement for having a real DB so local testing can be done, making real stored-procedure calls against a fake DB.

If you are building unit tests then you should not execute the stored procedure and you should stub this interface.
If you are building integration tests then you must have it all working.
In both cases your class shouldn't do it directly, you should have an inner handler like IDbHandler and during your unit tests you should mock it and during the integration tests you should use your concrete implementation.
The purpose of having a mock is to verify that the other side (DB in your case) got a request with the expected parameters but a physical component can't be mocked so just by adding an interface between your code and the physical component will enable those validations.
BTW I would start with having the unit tests and just afterwards add the integration tests.

Related

Integration tests - Setup data in database

I need to write integration tests for my layer that exposes methods of service. But I need my database to be in a certain state for the tests to pass
For example for testing the GetStoreByID method, I need to have store 1 in my database but not store 2 (for the ko test)
The database is developed and deployed by a another team using a sql project (dacpac)
I use Entity Framework 6.1.3 with an Edmx
What is the best way, in this case, to setup the data in database before tests ?
This link https://msdn.microsoft.com/en-us/library/dn314431(v=vs.113).aspx gives the Microsoft MSDN article on how to write tests using EF6 by faking out the database.
In summary the article covers the subject 'When writing tests for your application it is often desirable to avoid hitting the database. Entity Framework allows you to achieve this by creating a context – with behavior defined by your tests – that makes use of in-memory data.'
If your data access is separated by an interface (i.e. using something like IDBSet for each of the types), personally I'd avoid depending on the database completely where possible, and use either a fakedbsets (if you need to test repository/DAL code) or just mocking with moq or nsubstitute if you don't.
I know this doesn't specifically answer your question, but the best way to setup test data is do it in memory in my experience with as few external dependencies as possible. The database adds extra moving parts that you don't really want to have to depend on in unit/integration tests. This also adds complexities if you have a CI server etc... that you generally want to avoid.

Act on database before Unit Test loads data from [DataSource], or manually set TestContext.DataRows

I'd like to run a stored procedure in my database prior to loading test data from a [DataSource] in a Unit Test. This procedure takes a parameter that is specific to each test method.
How can I call the sp once per Test Method? I tried doing it in an attribute, which worked, but it's messy.
Alternatively, and this is what I'm really trying to do here, is there a way to load test data from SQL Server dynamically, or possibly intercept the sql call that Unit Test makes on a per TestMethod basis?
You could abstract how you get your test data with a wrapper. Instead of calling TestContext.DataRow[dataRowColumnName] directly wrap it with a new class. In this wrapper class you can override the values or use the test data from the database.

Unit Testing Legacy Code without DI

We are trying to add unit testing into our Business layer. The technology stack is asp.net web forms, WCF, ADO.Net calling stored procedures). The business layer is calling static methods on data classes, so it makes it difficult to introduce DI without making a lot of changes.
It may not be a conventional way to do it, but I'm thinking of keeping the DB in the unit test (dependency), but using it as a Test Db... either using an existing frozen db or having mocked data in tables. I was wondering about the feasibility of using a test db where the stored procedures are used like Mocks. Instead of duplicating the entire db, just create table names, named by the stored procedure.
The stored procedure would just call one table, and return static data... essentially, trying to emulate the functionality of Mocking data with something like Moq but from a DB perspective.
Can anyone recommend any designs that would include the DB in testing, that are still deterministic?
if you want to use the DB in the tests and have everything be deterministic then you need each test to have its own DB, which means creating (and potentially populating) a new db for each test.
Depending on how your DB layer creates its connection this is feasible. I have done similar by generating a DB using localDb in test setup with a GUID for the name and then deleting the DB again at the end of the test in the tear down.
It ends up being reasonably slow (not surprisingly) but having the DBs created on a Ram disk drive helped with that.
This worked ok for empty dbs, that then had schemas created by EF, but if you need a fixed set of data in the DB then you might need to restore it from a backup in the setup of the test
It seems to me that it's going to be a lot of work setting up your stored procedures to do what you want them to do when they are called for each test, and you still end up with the speed problems that databases always present. I'd recommend you do one or both of the following instead:
Use TypeMock, which has a powerful isolator tool. It basically changes your compilation to make it so that your unit test can mock even static methods.
Instead of just unit tests, try creating "acceptance tests," which focus on mimicking a complete user experience: log in, create object, view object (verify object looks right), update object, view object again (ditto), delete object (verify object is deleted). Begin each of these tests by setting up all the objects you'll need for this particular test, and end by deleting all those objects, so that other tests can run based on an assumed starting state.
The first approach gives you the speed and mockability of true "unit" tests, whereas the second one allows you to exercise much more of your code, increasing the likelihood that you'll catch bugs, even in things like stored procedures.

Testing a long running process

I have a time consuming operation that needs tested. The operation makes changes to a database. Current, the majority of my tests are very similar, a query is performed on the database to determine the expected result after the operation. Then, the operation under test is ran. Finally, the database is again queried to determine if the expected condition has been met. Since I am only querying the database in each test to determine the expected and actual results, and the function under test is always performing the same operations on the database. Is there a way that I could run the operation once and still test each condition in its own test?
The standard strategy for running unit tests on code that has side effects such as connecting to databases is to provide mock objects instead of a real database connection or other service, but it depending on how your code is structured this may be harder or easier to adopt.
Frameworks for inversion of control and dependency injection can be very helpful for this kind of purpose. The dependancy injection pattern makes sure that objects can have dependant implementations passed to them at runtime, rather than constructing them directly, for testing purposes or just to create more modular code. StructureMap is such a framework for C#, but there are others, such as Spring.NET.
Sounds like you want to be using Unit Testing Frameworks and/or Mocking Frameworks.
As a general rule, you shouldn't be writing additional queries to test the query has worked as expected on the database as these themselves will require development and testing.
Depending on the database you're writing to, you may be able to get the number of rows affected on the database (take a look at ##rowcount for SQL Server). But again, you're adding additional code just to do testing which should really be a separate activity.

Creating Database Mocks in ASP.NET MVC using Data from Existing Database

I have an existing ASP.NET MVC application with some sample data in the SQL Server database, which is working fine..
Assuming I have all of the necessary repositories and IOC in place, is there a tool that will extract the data from a group of tables, and "freeze-dry" it into a mock object (perhaps using an XML file to store the data), so that I can detach the database and use the mock data for my unit tests?
Depending on what exactly you are trying to test there might be different approaches.
If you want to test the data access logic then this is no longer unit test but integration test. For this kind of tests it is a good idea to be able to easily replace the real database with some lighter maybe even in-memory database like SQLite which will be reconstructed before running each test. If you are using an ORM this task is easy. All you need to do is to generate SQL scripts (INSERT INTO...) from your existing database, modify and adapt the dialect to SQLite (if necessary), read and inject into a SQLite file and finally all that's left is to instruct your data access layer to use SQLite dialect and connection string for the unit test.
Now if you are not using an ORM and your data access logic is tied to MSSQL things get uglier you will need a live database in order to perform those integration tests. In this case I would suggest you duplicate your real database which you would use for the tests by modifying only the connection string. Once again you will need to properly setup and teardown (preferably in a transaction) this test database in order to put it into a known state for the tests.
If you want to test code that depends on those repositories (such as your controllers for example) you don't need to even bother about mocking the data as your controllers depend on abstract repositories and not the real implementations (aren't they), so you could easily mock the methods of the repository in order to test the logic in the controllers.
This is actually a well known "test smell":
http://xunitpatterns.com/Obscure%20Test.html#General
From:
2098937: Proper way to Mock repository objects for unit tests using Moq and Unity
I don't know of a direct way to do what you're asking for, but MSSQL supports export to CSV, Access, and Excel. Although, this require you to change the Data Access Layer in your in your mid-tier, and furthermore, I don't feel this answers your question:
"freeze-dry" it into a mock object
This I'm not sure of. Is it feasible to just restore a backup of the database either on the same SQL server as a new database, or possibly on a dev SQL server?

Categories