Tutorial :TDD-friendly Singleton-like class



Question:

I have repository class that is used by at least 2 other classes. This repository class needs to be initialized - which is high in cost (querying database). Now, I create separate instances of repository wherever I need it. The thing is, that everytime I create repository it has to be initialized. How to design such repository to be TDD-friendly? The first thing in my mind was Singleton but it's not the solution.


Solution:1

Do you use any type of IOC container? Unity is my container of choice, and it contains a ContainerControledLifetimeManager which makes your class a singleton, but not managed by yourself.


Solution:2

I hope by TDD-friendly you mean 'testable' code. For a Singleton ObjectX, I think the most common way is to split the responsibility (SRP) of 'controlling creation' to another class so ObjectX does all the things it is supposed to do.

Then you have another class ObjectXFactory or Host or whatever you wanna call it that is responsible for providing a single instance for all clients (and providing thread sync if needed and so on)

  • Object X can be TDDed independently. You can create a new instance in your test case and test functionality.
  • ObjectXFactory on the other hand is also easy to test.. you just need to see if multiple GetInstance() calls return the same object. OR better delegate this responsibility to an IOC framework like Spring, which lets you declaratively mark an object definition to obtain singleton behavior (Saving you the effort of writing tests as well)

You just need to educate and conform to a Team convention that ObjectX constructor is not to be called - always use ObjectXFactory.CreateInstance(). (If you find that you have a awareness/discipline problem, mark ObjectX's ctor as internal and visible to only to the test assembly via the sneaky InternalsVisibleToAttribute) HTH


Solution:3

One answer for the TDD part is learn mocking.

Check out this excellent article by Stephen Walther:

http://stephenwalther.com/blog/archive/2008/03/23/tdd-introduction-to-rhino-mocks.aspx


Solution:4

Consider caching instances for performance improvement before you consider singletons. But for TDD friendly designs consider strategy injection so that 'slow' bits can be removed for testing and replaced with stubs and mocks. Try not to do db calls in tests if you can.


Solution:5

You can't do that -- at least not in a true TDD sense.

Relying on DI/IoC strategies such as Unity means your tests are dependent on an external component and are not tested in isolation.

The tests then become integration tests, not unit tests.

==Ignore the answer below here==

I guess you wanted to know how to make Repository testable.

Introducing an interface for it would allow you to mock or stub it, which will in turn make sure that you can test your objects independent of any concrete implementation of Repository.

I'll illustrate this using Rhino Mocks 3.5 for .NET 3.5:

Let's make an interface out of Repository, let's call that IRepository

public interface IRepository  {  }  

Now, since you need to use IRepository for two different objects, then let's just use generics so you can instantiate your repository with that:

public interface IRepository<T>  

of course that would mean that you would have some sort of find method:

{      public IEnumerable<T> Find(Criteria criteria)  }  

where your criteria object is some object that allows you to set what to look for, e.g., your where clause.

Now, you have your object:

public class SomeObject  {      IRepository<SomeObject> repository;        public SomeObject(){}        public IRepository<SomeObject> repository { get; set; }        IEnumerable<SomeObject> FindAll()      {          //let's assume new Criteria() will return all results          return respository.Find(new Criteria());      }  }  

You want to to test SomeObject such that FindAll() will return an expected set of results -- this is where Rhino Mocks would come in:

[TestFixture]  public class SomeObjectTests  {      [Test]      public void TestSomeObjectFindAll()      {          IRepository<SomeObject> stubRepository = MockRepsitory.GenerateStub<IRepsitory<SomeObject>>();            stubRepository.Expect(r => r.Find(new Criteria())              .Return(new List<SomeObject>{                           new SomeObject(),                           new SomeObject(),                           new SomeObject());            var testObject = new SomeObject { Repository = stubRepository };          IList<SomeObject> findAllResult = testObject.FindAll();            //returned list contains 3 elements, as expected above          Assert.AreEqual(3, findAllResult.Count)      }  }  

Note that the code above is not TDD best practice in all respects, but it's a place to start.

Key concept here is introducing interfaces to allow for loose coupling of objects, especially when the object tends to do things like access databases, file systems, etc.

There is a more comprehensive example and better examples on Ben Hall's article on Rhino Mocks.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »