Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit test service that is using PetaPoco.Database

I am using PetaPoco on my current project as a micro ORM and i must say that i like it. However, i found myself struggling with simple scenario - unit testing services that use PetaPoco.Database

public class MyService : IMyService
{
    private readonly PetaPoco.Database _database;

    public MyService(PetaPoco.Database database)
    {
        _database = database;
    }

    public void SaveSomething(MyObject myObject)
    {
        //...custom logic
        _database.Save(myObject);
    }
}

I am using IoC (Castle.Windsor) for injection of both IMyService and PetaPoco.Database wherever needed.

Now, when i try to unit test my service i am unable to properly mock stub PetaPoco.Database in order to verify that the Save method was properly invoked. I am using NUnit and Rhino.Mocks for unit testing and mocking.

[TestFixture]
public class MyServiceTests
{ 

    private PetaPoco.Database _database;

    [SetUp] 
    public void SetUp()
    {
        _database = MockRepository.GenerateMock<Database>("");
    }

    [Test]
    public void ShouldProperlySaveSomething()
    {
        //Arrange
        var myObject = new MyObject();
        _database.Expect(db => db.Save(Arg<MyObject>.Is.Anything));
        var myService = new MyService(_database);

        //Act
        myService.SaveSomething(myObject);

        //Assert
        _database.VerifyAllExpectations();   
    }

}

I am aware that this can be solved if i extract an Interface from PetaPoco.Database and do the mocking against it, or by virtualizing PetaPoco's methods that i want to mock, but the point is that i don't want to make changes to PetaPoco at all.

Is this doable?

like image 353
ljubomir Avatar asked May 26 '12 13:05

ljubomir


People also ask

Can unit tests use databases?

To test an application it is not enough to use unit tests. You must also perform functional testing and regression testing. Database access falls outside the scope of unit testing, so you would not write unit tests that include database access.

Should you mock database in unit tests?

Mocking and stubbing are the cornerstones of having quick and simple unit tests. Mocks are useful if you have a dependency on an external system, file reading takes too long, the database connection is unreliable, or if you don't want to send an email after every test.

Should unit tests touch the database?

Unit tests should never connect to a database. By definition, they should test a single unit of code each (a method) in total isolation from the rest of your system.


1 Answers

My branch located here: https://github.com/schotime/PetaPoco already has an interface defined for the Database class.

Also there is my new Fork https://github.com/schotime/NPoco or NPoco on nuget which has the same api.

I would use one of these. ;)

like image 76
Schotime Avatar answered Sep 28 '22 00:09

Schotime