Mindscape
  • Register
  • Login
  • YOUR CART IS EMPTY
home
Software
  • Developers Toolbox
  • LightSpeed
  • Raygun
  • WPF Elements
  • Web Workbench
  • Metro Elements
  • Silverlight Elements
  • NHibernate Designer
  • Phone Elements
  • WPF Diagrams
  • Simple DB management
  • Visual Tools for SharePoint
Downloads
Store
  • Buy online
  • Purchase order
  • Volume discounts
  • Reseller
  • Software license
  • Contact sales
Blog
Support
About
  • About Us
  • Contact
  • Testimonials
rss
twitter
facebook
Testing and Debugging Unit Testing Logging Profiling Using the Debugger Visualizer

Unit Testing

When undertaking unit tests it’s essential that the tests be repeatable. This means that developers need to ensure that the database is in an expected state at the beginning of each test run. To achieve this, tests can either be run against a real database with transactions or run against fake objects in memory.  This guide explores both approaches. Sample code uses the NUnit unit testing product, but can easily be adapted to any unit testing framework.

Using a Real Database

Setup a test version of your database. Typically we have set up two databases for a project:

·         ApplicationDatabase

·         ApplicationDatabase_Test

All of the test data will be stored in the ApplicationDatabase_Test.

Next, create a transaction test fixture.  The benefit of this is that all our test fixture classes can derive from the custom test fixture class and be ready with the transactional pattern for testing in place.

An example of the transactional TestFixtureBase

[TestFixture]
public abstract class TestFixtureBase
{
  private static readonly LightSpeedContext<MyModelUnitOfWork> _context =
    new LightSpeedContext<MyModelUnitOfWork>();
  static TestFixtureBase()
  {
    // configure LightSpeed
    _context.ConnectionString = @"Data Source=ORMapper;Initial Catalog=ORMapper; Integrated Security=SSPI";
    _context.Logger = new ConsoleLogger();
  }
  private TransactionScope _transactionScope;
  private MyModelUnitOfWork _uow;
  [SetUp]
  public virtual void SetUp()
  {
    _transactionScope = new TransactionScope();
    _uow = _context.CreateUnitOfWork();
  }
  [TearDown]
  public virtual void TearDown()
  {
    _uow.Dispose();
    _transactionScope.Dispose();
  }
}

In this code all tests are run within a TransactionScope and the changes are rolled back upon completion of the test.

Additionally, note that in the SetUp method we are creating a new unit of work and in the TearDown method we are destroying it by calling IUnitOfWork.Dispose. The creation of new units of work for each test is important because we want complete test isolation; that is, no test can affect the result of any other test. We achieve this isolation by having each test run in a new unit of work.

Once this is done the development of the actual tests can commence.

A simple unit test

[Test]
public void UpdatingContributionDescription()
{
  var contribution = _uow.Contributions.Single(c => c.Id == 1);
  contribution.Description = "Some new description";
  _uow.SaveChanges(true);
  var updatedContribution = _uow.Contributions.Single(c => c.Id == 1);
  Assert.AreNotSame(contribution, updatedContribution);
  Assert.AreEqual("Some new description", updatedContribution.Description);
}

This test finds the Contribution with Id 1 and then updates its Description attribute. We then call SaveChanges to flush our pending update to the database. Notice we pass true to the SaveChanges method. This is an idiomatic LightSpeed unit test pattern applicable whenever we want to verify a database update was made correctly. The SaveChanges method causes all pending updates to be flushed to the database, and the true argument signals that LightSpeed should additionally clear the identity map – the unit of work’s cache of the entities it is managing, which serves to prevent us loading the same Entity more than once. By clearing the identity map, we guarantee that subsequent requests for previously loaded objects hit the database and therefore allow us to validate that the database state of an entity is as we expect.

Using Fakes

In situations where in memory objects would be preferred there are helper classes included in LightSpeed to create fake entities and a test unit of work.

LightSpeed includes two classes to help support faking queries and entities: TestUnitOfWork and EntityFactory. Both of these are in the Mindscape.LightSpeed.Testing namespace.

TestUnitOfWork allows you to inject a fake result for a query. To do this, call the TestUnitOfWork.SetCollectionResult method, passing in the desired fake result. Subsequent calls to Find or FindBySql, or LINQ entity queries, will return the fake result rather than querying the database. TestUnitOfWork also allows faking of other query methods:

·         Call TestUnitOfWork.SetSingleResult to specify a fake result for FindOne or FindById

·         Call TestUnitOfWork.SetExpectedCountResult to specify a fake result for Count, or the LINQ Count() and LongCount() operators

·         Call TestUnitOfWork.SetExpectedCalculateResult to specify a fake result for Calculate, or for LINQ aggregate operators such as Sum()

·         Call TestUnitOfWork.SetProjectionResult to specify a fake result for Project, or for LINQ projection queries (where specific properties are selected into a named or anonymous type)

·         Call TestUnitOfWork.SetSearchResult to specify a fake result for Search

Note that fake results are returned directly – any query expression or LINQ Where operator is not applied!  Your test fixture should set up the expected fake results.

Creating a TestUnitOfWork and adding then selecting a fake entity

[Test]
public void FetchObjectByIdFromTestUnitOfWork()
{
  var uow = new TestUnitOfWork();
  var entity1 = EntityFactory.Create<Comment>(EntityState.Default, 1000);
  uow.Add(entity1);
  Assert.IsNotNull(uow.FindById<Comment>(1000));
}

EntityFactory helps you to create entities with predictable ID values and in states other than the New state. Thus, you can use EntityFactory to fake entities that have been loaded from the database (and therefore begin in the Default state).

Using Mocks

If you are interested in interaction based unit testing (often characterized by the use of mocks, fakes or stubs), LightSpeed exposes a few key interfaces that facilitate such an approach. The primary extension point providing substitutability in LightSpeed is the IUnitOfWork interface. Implementing (or mocking) IUnitOfWork provides complete control over all major LightSpeed operations such as querying and persistence. In order to make your test context use your mock IUnitOfWork, create an implementation of IUnitOfWorkFactory that returns your custom implementation and then assign your custom IUnitOfWorkFactory to the UnitOfWorkFactory property found on the LightSpeedContext object.

Some places in LightSpeed internally require a UnitOfWorkBase, not just an IUnitOfWork. Consider mocking UnitOfWorkBase rather than the interface, or using the TestUnitOfWork fake instead.

Data Products

  • LightSpeed ORM
  • NHibernate Designer
  • SimpleDB Tools
  • SharePoint Tools

DevOp Tools

  • Raygun

Visual Controls

  • WPF Elements
  • WPF Diagrams
  • Silverlight Elements
  • Phone Elements

Popular Products

  • Web Workbench

    Modern web development for Visual Studio!

  • Mindscape Megapack

    All Mindscape products for one awesome price!

Quick Links

  • Forums
  • Blog
  • Register
  • Login
  • Contact us
  • Twitter
  • Facebook
  • Google+
  • YouTube
  • Linkedin
  • Rss

© Mindscape 2025. Mindscape is a registered trademark of Mindscape Limited.

  • Terms
  • Privacy