I’ve been playing around with Telerik’s OpenAccess ORM for a while now and I am slowly falling in love with it. Since I started using it I have literally not touched my SQL Server Management Studio once except to view the content of my tables. Why? Because OpenAccess supports forward mapping. I create my class structure, add the Persistent attribute and OA does the rest. This means that I can focus on what I like best, which is programming and are able to postpone getting into the nitty-gritty of the database design until later. Much, much later.

Note that you should revisit the database design at one point. But for my current pet project OA does an excellent job for me.

But on to the business at hand: Unit Testing.

Telerik provides an excellent tutorial on how to use OpenAccess with Unit Test Frameworks such as NUnit and MSTest. It involves setting up a mini-framework to enable you to automatically rollback any database changes you make during any of your tests. It is excellent for testing the integration of your application with the database. But in my project, I have some business logic that works on my entity classes before they reach the database. Using Telerik’s approach (and Dimitar Kapitanov from the Telerik team makes a good case why this is indeed a good approach in this thread) you would need to assert that data was indeed written to the database (or not, as in my example) while in fact we aren’t interested in what happens with the database (since we used Telerik’s approach to test that earlier, right?). Mocking to the rescue.

Let’s introduce an example Person class:

[Persistent]
public class Person
{
  private string firstName;
  private string lastName;
 
  public string FirstName
  {
    get
    {
      return firstName;
    }
    set
    {
      firstName = value;
    }
  }
 
  public string LastName
  {
    get
    {
      return lastName;
    }
    set
    {
      lastName = value;
    }
  }
 
  public string FullName
  {
    get
    {
      return this.firstName + " " + this.lastName;
    }
  }
}

Nothing fancy there. Notice the Persistent attribute that tells OpenAccess we’d like to be able to save a Person to the database.

We also have a PersonService class which contains our business logic:

public class PersonService
{
  private readonly IObjectScope scope;
 
  public PersonService() : this( ObjectScopeProvider1.ObjectScope() ) { }
 
  public PersonService( IObjectScope scope )
  {
    this.scope = scope;
  }
 
  public void AddPerson( Person person )
  {
    if ( Blacklist.Contains( person.LastName ) )
    {
      return;
    }
 
    scope.Transaction.Begin();
 
    scope.Add( person );
 
    scope.Transaction.Commit();
  }
 
  public List<String> Blacklist = new List<String>();
}

Not terribly exciting either. We have a constructor that takes an object of type IObjectScope (a technique called constructor dependency injection) which we need to be able to use a mock ObjectScope. The business logic we’ll be testing checks whether a Person is blacklisted before adding him or her to the database (or not).

For comparison, here’s the Unit Test class that uses Telerik’s method. Note the need for the SetUp and TearDown methods for the database cleanup. Also note the calls to SingleOrDefault to check whether Jack and John were refused or added, respectively.

[TestFixture]
public class PersonServiceTestsWithoutMocking
{
  private IObjectScope scope;
 
  [SetUp]
  public void TestSetup()
  {
    scope = ObjectScopeProvider1.GetNewObjectScope();
    scope.Transaction.Begin();
  }
 
  [TearDown]
  public void TearDown()
  {
    if ( scope.Transaction.IsActive )
    {
      scope.Transaction.Rollback();
    }
    scope.Dispose();
  }
 
  [Test]
  public void PersonShouldNotBeAddedIfBlacklisted()
  {
    // Set up PersonService
    PersonService ps = new PersonService();
    ps.Blacklist.Add( "Sparrow" );
 
    // Jack Sparrow shouldn't be added to the database
    Person jack = new Person { FirstName = "Jack", LastName = "Sparrow" };
    ps.AddPerson( jack );
 
    Person sparrow = scope.Extent().SingleOrDefault( p => p.LastName.Equals( "Sparrow" ) );
    Assert.IsNull( sparrow );
  }
 
  [Test]
  public void PersonShouldBeAddedIfNotBlacklisted()
  {
    // Set up PersonService
    PersonService ps = new PersonService();
    ps.Blacklist.Add( "Sparrow" );
 
    // John Smith should be added to the database
    Person john = new Person { FirstName = "John", LastName = "Smith" };
    ps.AddPerson( john );
 
    Person smith = scope.Extent().SingleOrDefault( p => p.LastName.Equals( "Smith" ) );
    Assert.IsNotNull( smith );
  }
}

Again, please note that this way of Unit Testing is perfectly valid. I simply like my concerns a little more seperated :). So, to test just the business logic of my class, I use Rhino Mocks to remove the dependency on the database. All I really care about is that the method to add the Person to the database is called or not.

[TestFixture]
public class PersonServiceTestsUsingMocking
{
  [Test]
  public void PersonShouldNotBeAddedIfBlacklisted()
  {
    // Create our mock ObjectScope
    IObjectScope mockScope = MockRepository.GenerateMock();
 
    // Set up PersonService using the mock ObjectScope
    PersonService ps = new PersonService( mockScope );
    ps.Blacklist.Add( "Sparrow" );
 
    // Jack Sparrow shouldn't be added to the database
    Person jack = new Person { FirstName = "Jack", LastName = "Sparrow" };
    ps.AddPerson( jack );
 
    // As Jack is blacklisted, we assert that IObjectScope.Add wasn't called
    mockScope.AssertWasNotCalled( s => s.Add( jack ) );
  }
 
  [Test]
  public void PersonShouldBeAddedIfNotBlacklisted()
  {
    // Create our mock ObjectScope
    IObjectScope mockScope = MockRepository.GenerateMock();
    // Create our mock Transaction (we need this because of the calls to Transaction.Begin() and Transaction.Commit())
    ITransaction mockTransaction = MockRepository.GenerateMock();
 
    // We set the expectation that IObjectScope.Transaction will be called twice, for Begin() and Commit()
    mockScope.Expect( s => s.Transaction ).Return( mockTransaction ).Repeat.Twice();
 
    // Set up PersonService using the mock ObjectScope
    PersonService ps = new PersonService( mockScope );
    ps.Blacklist.Add( "Sparrow" );
 
    // John Smith should be added to the database
    Person john = new Person { FirstName = "John", LastName = "Smith" };
    ps.AddPerson( john );
 
    // As John isn't blacklisted, IObjectScope.Add should have been called
    mockScope.AssertWasCalled( s => s.Add( john ) );
 
    mockScope.VerifyAllExpectations();
  }
}

As you can see, you can totally remove the dependency on the database by using mocking. This way you can seperate testing your infrastructure from your business logic. The above example was deliberately kept simple, if you browse the Rhino Mocks documentation you’ll find that we’ve only scratched the surface of what is possible.

Hope this helps.

If you liked this post, please click on one of the advertisements below. Thanks!


8 Responses to “Exploring Telerik OpenAccess: Unit Testing your Business Logic using Rhino Mocks”

  1. 1 Larry

    Can you recommend other good mocking frameworks that support .NET?

  2. 2 Erik Burger

    Hi Larry,

    There is a pretty large amount of mocking frameworks available, all with their own strengths and weaknesses. The most popular for C# (as far as I know) are NMock, Rhino Mocks and TypeMock.

    A good list can be found on Wikipedia, along with some interesting articles.

    Hope this helps,

    Erik

  3. 3 Pete

    Hi Erik,

    I’ve also been using Rhino Mocks to avoid dependencies and focus on fine grained tests. Unfortunately, I’m a bit stuck when it comes to stubbing a [Persistent] class.

    For example, if you had:

    [Persistent]
    public abstract class Person
    {

    }

    Because it is abstract, it would be nice to call:

    mockRepository.Stub()

    but I always get an exception relating to
    Telerik.OpenAccess.PersistentAttribute.get_IdentityClassName()

    Any thoughts?
    (A work-around is to create a derived class without the [Persistent] property and stub that, but I don’t want to do that for every domain class!)

    Pete.

  4. 4 Erik Burger

    Hi Pete,

    I’m afraid I don’t quite get what your exact issue is. If you could provide some example code, that’d be great. My email is eburger at reversealchemy dot net.

    Cheers,
    Erik

  5. 5 Shane

    Hi Erik,

    I know this is kind of an old post, but I’ve been evaluating Telerik OA as well now and I like it too, but the one issue I’ve had is just this. Your example is a good one, but what if you needed to perform a calculation on multiple objects it’s much different than just asserting that a method was called or not. I’ll look at Rhino mocks as you mentioned maybe it can do this as well, but I wanted to see if you have gone done this path already.

    Thanks,

    Shane

  6. 6 Erik Burger

    Hi Shane,

    This is exactly one of the situations where mocking shines; it can not only assert whether a method was called but it can also return fixed values (that you might normally get through a web service or somesuch). So for testing your calculation you’d have your object return fixed values (and in a different test suite you’d test that those object actually retrieve/calculate their values correctly.

    Does that make sense?

    Erik

  7. 7 James Legan

    Erik,

    I have been going back and forth with Telekrik’s JustMock team trying to accomplish exactly what you have achieved here, breaking the database dependency for unit testing, to mock out the database using the current implementation of OpenAccess with all of the changes that came in 2010. Do you know if this is possible with JustMock? Should I explore RhinoMock instead? I am an IIS hosted WCF Web Service dev and spend most of my time writing business logic surrounding entity classes and the methods that use them. You wouldn’t happen to have an updated version of this using the newer version of OpenAccess would you?

    Thanks,

    Jim

  8. 8 Erik Burger

    Hi Jim,

    Unfortunately I do not have an updated version for you. I am positive what you are trying to achieve is possible using JustMock but RhinoMock is an excellent alternative if it takes too much effort to make it work. I’ve worked with both frameworks and they’re both very complete, with each having its strengths and weaknesses.

    Erik

Leave a Reply


*