tags:

views:

36

answers:

1

Is there any way to have a mock constructed instead of a real instance when testing code that calls a constructor?

For example:

public class ClassToTest
{
  public void MethodToTest()
  {
    MyObject foo = new MyObject();
    Console.WriteLine(foo.ToString());
  }
}

In this example, I need to create a unit test that confirms that calling MethodToTest on an instance of ClassToTest will indeed output whatever the result of the ToString() method of a newly created instance of MyObject.

I can't see a way of realistically testing the 'ClassToTest' class in isolation; testing this method would actually test the 'myObject.ToString()' method as well as the MethodToTest method.

+3  A: 

Not really. Your ClassToTest is hard to test because of its design. If you want to be able to swap out its dependencies for mock objects, then you need to think about how these dependencies are injected - but just creating them in the constructor is not an approach that is going to help you. You could use constructor injection:

public class ClassToTest
{
  MyObject _foo;
  public void MethodToTest(Myobject foo)
  {
    _foo = foo;
    Console.WriteLine(foo.ToString());
  }
}

or you could use property injection:

public class ClassToTest
{
  public MyObject Foo { get; set; }
  public void MethodToTest()
  {
  }
}

The former may suit your example more given you want to write out the console there; it is often the best approach when your dependency is a must have dependency for the object rather than an optional one.

You could do a lot worse than exploring the concepts of dependency injection and inversion of control.

David M
There is a similar problem with using the static method WriteLine on Console. This would be difficult to test. Personally, I wrap up BCL classes such as Console into a class that has an instance method WriteLine in it which calls the real Console on your behalf. Then in the test, you inject a mocked wrapper and assert against that.
Colin Desmond
I considered that, and certainly in some cases it's probably a better option regardless of testing, but my main concern is that in some cases it may not be a good idea to allow client code to provide the object that's to be used by 'ClassToTest'. Also, in some cases it may just be impossible for client code to provide a suitable instance, if only ClassToTest contains the data necessary to construct it.I had hoped that it may be possible to 'override' .NET's class registry and provide your own implementation of a class, i.e. a mock in this case.
Flynn1179