Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing / mocking a database in .Net

I have a webservice which basically just executes some stored procedures, transforms the data and sends it to the browser. No fancy ORM mapper or something like that involved. To be able to write test without accessing the database, I have done the following:

  • I have extracted all calls to the DB into one class. The methods return just the DataSet and DataTable objects.
  • Executed a sample call for each method and serialized the DataSet/DataTable to disk.
  • Extracted an interface exposing all available methods.
  • Implemented a fake database class which just loads the serialized data and returns it.

Now I have serialized sample results which I can check in with my project, and I can use the fake database in my tests.

This works quite well for me. Is there some framework which makes creating and loading the sample data easier? My current project is small, but I would use the same schema in larger projects.

Update:

Obviously all answers are not wrong, but miss the point. I'm aware of the basics of unit testing. But my code is working with DataTables, so I would have to somehow fake my DataTables. Building a DataTable from scratch is not an easy task, and it would bloat my tests and reduce readability. In my case, it would be quite impossible to generate useful sample data by hand.

Therefore, I executed some sample calls against a sample database to get some DataTables. I have serialized these tables to disk and use the serialized versions to create my fake DataTables when testing. That way the tests are independent of the database.

There are different options regarding how to structure the code, to make deserialization of the tables easier. But those are implementation details which don't need a discussion at this point. My problem is the following:

Managing the sample calls and (de)serializing the tables is tedious work. I was looking for some tools to make this easier.

like image 585
Achim Avatar asked Apr 05 '11 09:04

Achim


People also ask

How do I mock database connection in Xunit?

You should adhere to Interface Segregation and Dependency Inversion principle by using Inversion of Control with the help of Dependency Injection. This way, you can create a MockDB2Connection, which you inject into the constructor, in your unit tests, while in your real code, you pass a proper DB2Connection.

What is mocking framework C#?

Mocking Frameworks (Moq, NSubstitute, Rhino Mocks, FakeItEasy, and NMock3) are used to create fake objects. We can stub, i.e., completely replace the body of member and function. It is used to isolate each dependency and help developers in performing unit testing in a concise, quick, and reliable way.

Why do we mock the database?

Mocks help to emulate and examine outcoming interactions. These interactions are calls the system under test (SUT) makes to its dependencies to change their state. Stubs help to emulate incoming interactions. These interactions are calls the SUT makes to its dependencies to get input data.


2 Answers

From reading the other answers and various comments you've made, it seems you want an easier way to generate large populated datasets for integration testing that doesn't hit the database.

NBuilder is a great open-source library that I've successfully used to create large amounts of test data. Simply combine NBuilder, a few basic POCO object classes, and some reflection - you'll have plenty of huge datatables you can easily combine into datasets in no time:

public class Person {     public string First { get; set; }     public string Last { get; set; }     public DateTime Birthday { get; set; } }  private DataTable GenerateDataTable<T>(int rows) {     var datatable = new DataTable(typeof(T).Name);     typeof(T).GetProperties().ToList().ForEach(         x => datatable.Columns.Add(x.Name));     Builder<T>.CreateListOfSize(rows).Build()         .ToList().ForEach(             x => datatable.LoadDataRow(x.GetType().GetProperties().Select(                 y => y.GetValue(x, null)).ToArray(), true));     return datatable; }  var dataset = new DataSet(); dataset.Tables.AddRange(new[]{         GenerateDataTable<Person>(50),         GenerateDataTable<Dog>(100)}); 
like image 70
Bermo Avatar answered Oct 10 '22 21:10

Bermo


To unit test the transformation you really shouldn't need to mock the database at all. I suspect that you've tightly coupled the transformations with you database calls. What you want to do here is extract all your transformation logic into a class of it's own like the following:

public static Transformations {     public static DataSet TransformationA(DataSet dataSet)     {         //transformation logic here     }      public static DataSet TransformationB(DataSet dataSet)     {         //transformation logic here     } } 

With this you can unit test only the transformations logic by passing in a dataset and then asserting the dataset returned has the correct transformations applied to it. This will prevent you from having to implement another data store (your 'fake' database) for testing purposes only.

Hopefully this helps

like image 31
stuartf Avatar answered Oct 10 '22 21:10

stuartf