Mocking Enterprise Lib 5 'Database'

Is it possible to mock the corporate library of version 5 of the Database? If so ... how?

There is no IDatabase interface (which is a mystery, because although Microsoft P & P will be more on the ball about the benefits of testing that demonstrate such an interface).

I have a repository class that used the EntLib 5 Application Application Block.

I am testing modular installations in this class and need to wear out depending on the database object. This class is now passed through the database through its constructor and uses the Database object to perform operations on Db.

I use the following to allow the database instance to be transferred to my repository:

Container.RegisterType<IFooRepository, FooRepository>( new InjectionConstructor( EnterpriseLibraryContainer.Current.GetInstance<Database>("FooDbConnStr") ) ); 

I do not want these unit tests to become integration tests.

I tried using Moq to create a dynamic layout of the database type, but it turned out to be difficult, because the database requires a connection string and DbProviderFactory in its constructor. Perhaps if there was such a thing as a MockDbProviderFactory.

This is the form unit test takes:

EntLib UnitTest Attempt to Mock Database

In addition, I also find that using a static logger is very difficult to verify. I hope I missed some trick here, but I must say that so far I am disappointed with testability.

+6
c # unit-testing enterprise-library
source share
4 answers

I used FakeItEasy http://code.google.com/p/fakeiteasy/ .

I created a SqlDatabase layout (inherits from a database with a friendlier constructor) passed it to FooRepostory, called the function to be tested and approved the 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); } 
+2
source share

FWIW, I was able to mock SqlDatabase using Moq. SqlDatabase has the SqlClientPermission attribute, which doesn’t work very well with Castle Windsor (using Moq). I had to explicitly instruct Castle to ignore the SqlClientPermission attribute in order to get the test to work (see Line 1 in the example below). The following is an example unit test (borrowing an example from Stephen H)

  [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."); } 
+3
source share

The database is an abstract base class, and the DbProviderFactory is also abstract, so you can simulate both of them. While you are mocking the operations that you invoke in the database type (almost everything that is virtual, so you should be fine) you really do not need to do anything in the factory provider. And the connection string can be empty or null or any other.

+1
source share

I personally downloaded the source code and used ReSharper to retrieve the interface for the database object. It was rebuilt, and I used my own binaries. Wala - the interface! Hint: Interfaces are easy to fake. Why the Microsoft P & P group did not do this, I do not know.

+1
source share

All Articles