Reputation: 55
Rhino Mock Experts please help.
Below Example of rhino mock is working fine.
internal class TestClass
{
private ITestInterface testInterface;
public TestClass(ITestInterface testInterface)
{
this.testInterface = testInterface;
}
public bool Method1(int x)
{
testInterface.Method1(x);
return true;
}
}
[TestClass]
public class UnitTest2
{
[TestMethod]
public void TestMethod1()
{
ITestInterface mockProxy = MockRepository.GenerateMock<ITestInterface>();
TestClass tc = new TestClass(mockProxy);
bool result = tc.Method1(5);
Assert.IsTrue(result);
mockProxy.AssertWasCalled(x => x.Method1(5));
}
}
Problem i am facing as per above code is i need to create a constructor in all child classes like this:-.
internal class testclass1 : TestClass
{
protected testclass1(ITestInterface testInterface) : base(testInterface)
{
}
}
Is there any workaround for it as i am having around 50 child classes?
Upvotes: 2
Views: 1371
Reputation: 8408
As mentioned in my comment to your question, this isn't really an issue caused by mocking or unit testing. It is a natural consequence of using constructor injection (ie. providing Dependencies as constructor arguments). An alternative is to use property injection, that is, creating a writable property by which you can set your ITestInterface object, like so:
public class TestClass {
public ITestInterface FooBar {protected get; set; }
}
This way, all derived classes have access to FooBar without the need to create their own constructor that passes the ITestInterface through to the base class.
However, this has other consequences: constructor injection typically expresses mandatory dependencies. Without that dependency, the class won't work. Property injection, however, is often used to express optional dependencies or a way to override the default behavior. This distinction isn't set in stone, though, and if your really have dozens of classes deriving from TestClass constructor injection can become a real burden to maintain.
If an object requires constructor arguments it is very obvious to the user that he must pass the required dependencies. With property injection it is much easier to forget to set the property to properly set up the object (if the dependency is required). Also, with constructor injection you only need to check if the dependency has been provided once (in the constructor), while with property injection it's more likely that you need to check the validity of the dependency each time you use it.
Again, if using constructor injection results in a maintenance nightmare because you have many sub classes, property injection is still a viable option despite what I wrote before. You could additionally express the required property dependencies by using an initialization method like:
public static class TestClassInitializer{
public T Initialize<T>(this T t, ITestInterface dependency) where T:TestClass{
t.FooBar = dependency;
return t;
}
}
If you can force yourself to construct objects like this:
var tc = new DerivedTestClass().Initialize(mockTestInterface);
You have a single point where you can modify required dependencies. If you now need a second dependency, just update the signature to include the second dependency
public static class TestClassInitializer{
public T Initialize<T>(this T t, ITestInterface dependency, IOtherDependency other) where T:TestClass{
t.FooBar = dependency;
t.OtherDependency = other;
return t;
}
}
And all places where you call Initialize will break at compile time. This is a good thing(!) because you need to provide the required dependencies. However, you only need to update those places, not the 50 derived classes to add an additional dependency. If you had used constructor injection you what have needed to update all 50 classes and all places where you instantiate them.
Also: if you know that your derived classes only have a default constructor, you can create a factory method for all classes :
public static class TestClassFactory{
public static T Create<T>(ITestInterface dep1, ITestInterface dep2) where T :TestClass, new(){
return new T{FooBar = dep1, OtherDependency = dep2};
}
}
Instead of new DerivedTestClass().Initialize(...)
you can now use TestClassFactory.Create<DerivedTestClass>(mockedDep1, mockedDep2);
. You can make the actual constructors (protected) internal if you want as long as the TestClassFactory is in the same assembly (or in an assembly that can access the internal constructors through InternalsVisibleTo).
All this is less of an issue if you use a dependency injection framework/IoC container, as it won't forget to provide the dependencies once setup correctly.
Upvotes: 4