How to use Moq to mock database method call? - c#

I have question about mock Database. I saw something using moq to mock database call like ExecuteScalar, ExecuteNonQuery and etc. See the link http://www.codeproject.com/Articles/478504/Moq-Mock-Database.
But I am not able to find any information about mock method DiscoverParameters, and ExecuteDataSet.
And repository interface usually a solution for it.
How can I test the DbCommand execute result code with Moq?

I agree that there could definitely be ways in which the database could be mocked. But the real question is should we? Per my understanding mocking makes sense when you are trying to test behaviors. Aren't or shouldn't database tests be state dependent? If am trying to get number of users from a city, and if I am specifically unit testing my database access layer, I would be much more confident if my C# code actually converts in SQL, fire queries and returns real data. The onus of creating and destroying this data surely lies with the developer. It's a problem to maintain test data, but I think it's a good problem to have and solve.
Mocking the data access layer when you unit test layers that depend on it definitely makes sense. But mocking the database itself while testing the data access layer sounds a) like an over kill b) incomplete.

#user3551790 Hi I have mocked ExecuteDataSet using Moq as below
string connectionString = "server=xx.xx.xx.xx;Trusted_Connection=false;user id=user;password=passowrd;database=DBName;Connect Timeout=360;";
var sqlConnection = new SqlConnection(connectionString);
var command = sqlConnection.CreateCommand();
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Data.SqlClient.SqlClientPermissionAttribute));
DataSet dsResult = new DataSet();
dsResult.Tables.Add(new DataTable());
dsResult.Tables[0].Columns.Add("Column1");
DataRow dr = dsResult.Tables[0].NewRow();
dsResult.Tables[0].Rows.Add(dr);
dsResult.Tables[0].Rows[0].ItemArray = new object[] { DBNull.Value};
dsResult.Tables.Add(new DataTable());
var mockDb = new Mock<SqlDatabase>(connectionString);
mockDb.Setup(a => a.GetStoredProcCommand("SP_NAME")).Returns(command);
mockDb.Setup(a => a.ExecuteDataSet(command)).Returns(dsResult);
However since DiscoverParameters is a non virtual method you cannot mock it using Moq. You will have to go for Typemock

Related

Any point unit testing methods that use EF or Linq?

I am writing unit tests for my service layer, and i completely see the point of creating unit tests to validate logic. For example, if i create a function that adds two numbers, sure write a unit test for this.
But if in my service layer method i have something like this
public ICollection<MyEntity> GetAll()
{
return _context.MyEntities
.Where(e => !e.IsDeleted)
.ToList();
}
What is the point in unit testing this? Since i am getting this from a database, it seems stupid to mock the database, because i am then just assuming that Linq is working as it should be?
Would it not be better to test this against an actual "test" database with sameple data in it. This way i can see if the number of record that are retrieved from the database match what i would expect?
I know that testing against a database, makes this more of a integration test, but is it really valid for unit testing?
What if i take another example, say this
public int Delete(long id)
{
_context.Database.ExecuteCommand("DELETE FROM myTable WHERE Id = ?", id);
return _context.SaveChanges();
}
How can this function be unit tested? If i mock _context.Database and create a unit test that checks if _context.SaveChanges is being called (which i see no point in what so ever), there is no guarntee that it will actually delete my data. WHat if i have a foreign key constraint? The mock would pass, but the actual method would fail really?
I am just starting to think, that unless a method actually calculates some sort of logic, i dont see the point/reason for creating a unit test, especially when using Entity framework?
I think it makes sense to unit test nearly all types of functions:
"What is the point in unit testing this? Since i am getting this from a database, it seems stupid to mock the database, because i am then just assuming that Linq is working as it should be?"
You are not testing Linq, but you are testing the function; the function has the name GetAllAsync; and simply I can assume that this will return all of MyEntity instances stored in database. But it simply returns only deleted items; unit testing is not just verifying if the function works properly; it is also a way to check whether this function is named properly.
Also this function has a problem; what if
_context.MyEntities(e => !e.IsDeleted) returns null? ToList will throw an exception. Then unit testing will help to identify potential problems if you test for extreme values.
Also, unit testing forces you to employ abstraction. If you can not unit test a method, the method may have problems, you need to investigate that method and re-factor.
_context.Database.ExecuteCommand("DELETE FROM myTable WHERE Id = ?", id); In my opinion this line of code needs to stay somewhere else, not in the service layer (in repository maybe?). What if id is "-1"? how will you handle the exception?
I think it is really hard to state a generic rule about not unit testing methods that include Linq.
Why would you unit test a function that adds two numbers? You're not testing the + operator any more than you're trying to test LINQ or EF. You are testing behaviour so it's perfectly valid to test things that you might assume "just work". If, for example, I banned the use of EF in your application, you'd still need a test to ensure correctness in whatever you replaced the function with.
Where do you want to draw the line?
For database related code, I would actually test against a real database, not a mock. It's the only way you can be sure that the SQL is valid (whether you write it by hand or let an ORM generate it for you). There are tools to make that easier, like Respawn.

How to write an integration test in NUnit?

We are two students writing our bachelor thesis and we have developed a Windows Application, which should be able to aid a restaurant in various communication processes. Fundamentally, it should be able to present information about the order from the moment a guest send it to it is served.
We have omitted to test during the development but have decided to write unit tests now. Nevertheless, we have found out that the most suitable test we can write to our system now are integration tests because all the methods in our classes are bound to SQL stored procedures via LINQ to SQL. We are aware of the usage of stubs to fake out a dependency to a database, but when our database already is implemented together with all the functions, we figured it would give us more value to test several methods together as an integration test.
As seen in the code below we have tried to follow the guide lines for a unit test, but is this the right way to write an integration test?
[Test]
public void SendTotalOrder_SendAllItemsToProducer_OneSentOrder()
{
//Arrange
Order order = new Order();
Guest guest = new Guest(1, order);
Producer producer = new Producer("Thomas", "Guldborg", "Beverage producer");
DataGridView dataGridView = new DataGridView { BindingContext = new BindingContext() };
order.MenuItemId = 1;
order.Quantity = 1;
//Act
guest.AddItem();
dataGridView.DataSource = guest.SendOrderOverview();
guest.SendOrder(dataGridView);
dataGridView.DataSource = producer.OrderOverview();
var guestTableOrder = producer.OrderOverview()
.Where(orders => orders.gtid == guest.GuestTableId)
.Select(producerOrder => producerOrder.gtid)
.Single();
//Assert
Assert.That(guestTableOrder, Is.EqualTo(guest.GuestTableId));
}
Yes, generally speaking, this is how to write a unit test/integration test. You observe some important guidelines:
Distinct Act-Arrange-Assert steps
The test name describes these steps (maybe it should have something like "ShouldSendOneOrder" at the end, "Should" is commonly used to describe the Assert).
One Assert per test.
I assume you also obey other guidelines:
Tests are independent: they don't change persistent state, so they don't influence other tests.
Test realistic use cases: don't arrange constellations that violate business logic, don't do impossible acts. Or: mimic the real application.
However, I also see things that raise eyebrows.
It's not clear which act you test. I think some "acts" belong to the arrange step.
A method like producer.OrderOverview() makes me suspect that domain objects execute database interaction. If so, this would violate persistence ignorance. I think there should be a service that presents this method (but see below).
It's not clear why dataGridView.DataSource = producer.OrderOverview(); is necessary for the test. If it is, this only aggravates the most serious point:
Business logic and UI are entangled!!
Method like guest.SendOrderOverview() and producer.OrderOverview() are smelly: why should a domain object know how to present its content? That's something a presenter (MVP) or a controller (MVC) or a view model (MVVM) should be responsible for.
A method like guest.SendOrder(dataGridView) is evil. It ties the domain layer to the UI framework. This fixed dependency is evil enough, but of course you also need values from the grid view inside this method. So the business logic needs intimate knowledge of some UI component. This violates the tell - don't ask principle. guest.SendOrder should have simple parameters that tell it how to do its task and the domain shouldn't have any reference to any UI framework.
You really should address the latter point. Make it your goal to run this test without any interaction with DGV.
If you continue to bound sql in class,your test is not a big problem.
You can use this method when the program logic is very simple,But I suggest you study The Repository Pattern,as the logic becomes more complex.

How to write integration test against database

Lets say I have a class like below.
I'm not sure how I would write a unit/integration test against it. Does it need refactoring?
Would it simply be to add an Add/Find method (which it would have in reality), call the Add in the test then call the Delete and then the Find?
public class Repository
{
public void DeleteProduct(int id)
{
var connstring = ""; //Get from web.config
using(SqlConnection conn = new SqlConnection(connstring))
{
conn.Open();
SqlCommand command = new SqlCommand("DELETE FROM PRODUCTS WHERE ID = #ID")
command.Paramaters.Add("#ID", id)
command.ExecuteNonQuery();
}
}
}
The golden rule is not to test framewkrk's code. Unless this method would have no custom logic there is nothing to test.
I think what you trying to achieve is to separate Repository to make unit-testing easy. The best way of doing this would be to create interface for your repository and mock it.
If you really want to create some integration tests then you have to create some test database where you could make your nuclear bombs experiments.
My suggestion - write an Integration test for repositories (since you are using a framework for data access), unless there is more than CRUD that you are doing in the repository.
Add/Find are all individual Repository methods, and they need to be tested themselves.
I would recommend, use Setup to setup seed data, that you know you can act on. In this case, insert records into Products table.
Then Act: Call Repository.Deleteproduct(<product id created in setup>)
Assert that: Product created in setup is deleted (Query the database again to check).
If you are using an ORM, this test would also test your mappings for Product.
I have never added unit test for database calls. This is definitely more of an integration test. There is nothing observable for you to check.
I know that Java had some tools for this that fitted into JUnit. IT requires that you write XML files that mimic before and after and then it compares the contents of the table to the XML file. I am sure that .Net will have something similar. However I am not sure that it is worth it. I found those tests to be incredibly brittle and provide very little value.
I would suggest take the pragmatic approach and don't write test for database objects. Rather test those object that interact with your database objects.

Is there a proper way to test EF Code First Repository Pattern?

This comes after 3 days of researching and writing code. I have EF Code First ( EF5) and a generic repository pattern built on top of it.
Now I have ICustomerRepository<Customer> : IRepository and
CustomerRepository : RepositoryBase<MyContext> , ICustomerRepository. So when I go about testing this I find that I have to write A FakeDbContext , A Fake IDbSet and then Fake the data as well and do a lot more as well. All this when I know that I am going to test Linq to Objects with my in memory data and Linq to Entities will require another suite of tests in the form of integration tests. So, either my code structure is wrong and thus writing unit tests is so difficult or there is a better way to write tests that I am unaware of or I should just have Integration Tests. I am using NUnit and MOQ.
Edit : What is it that I am trying to test ?
I am trying to check methods like GetCustomersByType , Add , GetOrderPlacedByCustomer . Trying to see if the logic inside those methods is correct. This what unit test are for , I guess.
I think you will get a lot more if you create a test initialize method that will setup all the data before each test,ie.black box testing. In the end, you will know that repository layer is doing it's job properly on real database, not a mocked one.
For example:
public static void Init()
{
_unityContainer = new UnityContainer();
_unityContainer.LoadConfiguration();
_persistenceFactory = _unityContainer.Resolve<IPersistenceFactory>();
_unitOfWork = _persistenceFactory.GetUnitOfWork();
_usersRepository = _persistenceFactory.GetUsersRepository();
_usersRepository.RemoveAll();
_unitOfWork.Commit();
}
public static void InsertTestData()
{
User u = new User("johndoe#gmail.com", "John Doe", "johndoe");
_usersRepository.Add(u);
_unitOfWork.Commit();
}
You can use TransactionScope to simulate DB access, but not committing the actual changes to the database. Something like this:
[TestMethod]
public void AddingShouldWork()
{
using (var transaction = new TransactionScope())
{
var repository = new ICustomerRepository<Customer>();
var customer = new Customer();
customer.Name = "OEM Computers Inc.";
repository.Add(customer);
}
}
By not calling transaction.Complete() the operations are treated just like a rollback, resulting in no database insert. This is just the behaviour you want for unit (not integration) testing. You can also use Moq<Customer> to not create real entities.

Mocking Enterprise Lib 5 'Database'

Is it possible to mock the enterprise library 5 version of 'Database'? If so... how?
There is no IDatabase interface (which is a mystery as I though Microsoft P&P would be more on the ball about testability benefits of exposing such an interface).
I have a Repository class which used EntLib 5 Data Access Application Block.
I am retro fitting unit tests into this class and need to mock out the dependency on the Database object. This class is now passed the Database via its constructor and uses a Database object to perform operations on the Db.
I use the following to resolve an instance of the Database to be passed to my Repository:
Container.RegisterType<IFooRepository, FooRepository>(
new InjectionConstructor(
EnterpriseLibraryContainer.Current.GetInstance<Database>("FooDbConnStr")
)
);
I don't wish these unit tests to become integration tests.
I have tried using Moq to create a dynamic mock of the Database type, but this has proved tricky as Database requires a connection string and a DbProviderFactory in its constructor. Maybe if there was such a thing as a MockDbProviderFactory.
This is the form that the unit test is taking:
Aside: I also find the use of a static logger class very difficult to test. Hopefully I am missing some trick here, but I must say I am disappointed with testability thus far.
FWIW, I was able to mock a SqlDatabase using Moq. SqlDatabase has a SqlClientPermission attribute which does not play well with Castle Windsor (used by Moq). I had to explicitly instruct Castle to ignore the SqlClientPermission attribute to get the test to work (see line 1 in the example below). Below is a sample unit test (borrowing Steven H's example).
[TestMethod]
public void FooRepo_CallsCorrectSPOnDatabase()
{
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Data.SqlClient.SqlClientPermissionAttribute));
var mockSqlDb = new Mock<SqlDatabase>("fake connection string");
mockSqlDb.Setup(s => s.GetStoredProcCommand("sp_GetFoosById"));
var sut = new FooRepository(mockSqlDb);
sut.LoadFoosById(1);
mockSqlDb.Verify(s => s.GetStoredProcCommand("sp_GetFoosById"), Times.Once(), "Stored Procedure sp_GetFoosById was not invoked.");
}
I used FakeItEasy http://code.google.com/p/fakeiteasy/.
I created a mock of SqlDatabase (inherits from Database with a friendlier constructor) passed it to the FooRepostory, called the function under test and asserted expected calls that were made to the Database.
[Test]
public void FooRepo_CallsCorrectSPOnDatabase()
{
var mockDb = A.Fake<SqlDatabase>(x => x.WithArgumentsForConstructor(new object[] { "fakeconnStr" }));
var sut = new FooRepository(mockDb);
sut.LoadFoosById(1);
A.CallTo(() => mockDb.GetStoredProcCommand(Db.SProcs.GetFoosById)).MustHaveHappened(Repeated.Once);
}
Database is an abstract base class, and DbProviderFactory is also abstract, so you can mock them both out. As long as you mock out the operations that you're calling on the Database type (just about everything there is virtual so you should be ok there) you don't actually need to do anything in the provider factory. And the connection string can just be empty or null or whatever.
I personally loaded up the source code and used ReSharper to Extract Interface for the Database object. It rebuilt and I used my custom binaries. Wala - An interface! Hint: Interfaces are simple to mock. Why Microsoft P&P group didn't do this, I do not know.

Categories

Resources