Say I have a class that is being called from within my MainClass method that I am testing.
public class MainClass
{
private readonly SubClass;
// constructor not shown
public method TestMethod()
{
var data = SubClass.MethodA();
// ...some code
var moreData = SubClass.MethodB(someOtherData);
// ...more code
}
}
Using RhinoMock, I'd like to create a stub for SubClass.MethodA() to return a specified set of data in the test, however when calling SubClass.MethodB(), I want to call the original implementation.
I wouldn't want to break out the SubClass' two methods out into their own classes as they fit in SubClass. Is there a way in RhinoMock to stub out one method while calling another method in the same class (that is not a stub)?
I would use the extract and override test pattern and a simple stub for this.
This doesn't explicitly use Rhino though but will do for your scenario.
If you don't want to go down this path consider injecting Subclass into MainClass via a constuctor, public setter or parameter, and then you can have more control of mocking subclass first.
The idea is to make a virtual method that a sub class stub can override to take control of the behaviour of a part of a class under test.
public class MainClass
{
private readonly SubClass _subClass;
// constructor not shown
public void TestMethod()
{
var data = SubClassMethodACall();
// ...some code
var someOtherData = "";
var moreData = _subClass.MethodB(someOtherData);
// ...more code
}
protected virtual string SubClassMethodACall()
{
return _subClass.MethodA();
}
}
public class SubClass
{
public string MethodA()
{
return null;
}
public string MethodB(string s)
{
return null;
}
}
namespace Tests.Unit
{
public class MainClassStub : MainClass
{
private readonly string _returnValueForMethodA;
public MainClassStub(string returnValueForMethodA)
{
_returnValueForMethodA = returnValueForMethodA;
}
protected override string SubClassMethodACall()
{
return _returnValueForMethodA;
}
}
[TestFixture]
public class TestClass
{
[Test]
public void TestMethod()
{
var mainClass = new MainClassStub("this is the test value returned");
//.. rest of test
}
}
}
Related
I try to create a good testable repository class to use with Moq. I don't want duplicate my selector methods (GetAll, Get, ...). My implementation works fine but SonarSource reports an error RSPEC-1699 Does anyone know of a better implementation?
var areas = new Area[] { ... };
var areaRepositoryMock = new Mock<BaseAreaRepository>() { CallBase = true };
areaRepositoryMock.Setup(m => m.Initialize()).Returns(areas);
Base Class
public abstract class BaseAreaRepository
{
protected Area[] _areas;
protected BaseAreaRepository()
{
this._areas = this.Initialize();
}
public abstract Area[] Initialize();
public Area[] GetAll()
{
return this._monitoredAreas;
}
public Area Get(int id)
{
return this._areas.FirstOrDefault(o => o.Id.Equals(id));
}
}
MyAreaRepository
public class MyAreaRepository : BaseAreaRepository
{
public override Area[] Initialize()
{
return //Load data from an other source
}
}
The RSPEC-1699 Constructors should only call non-overridable methods doens't have anything with the unit tests it will remain there regardless how you are going to test it.
Does anyone know of a better implementation?
I would like to propose another approach in order to avoid this violation and make your code even more testable.
The idea is instead of the base class use composition and DI principle.
public interface IAreaContext
{
Area[] GetAreas();
}
public class AreaRepository
{
private IAreaContext _areaContext;
protected BaseAreaRepository(IAreaContext areaContext)
{
_areaContext = areaContext;
}
public Area[] GetAll()
{
return _areaContext.GetAreas();
}
}
Then you could define multiple implementations of IAreaContext and injext:
public class MyAreaContext : IAreaContext
{
public Area[] GetAreas()
{
return //Load data from an other source
}
}
public class MyOtherAreaContext : IAreaContext
{
public Area[] GetAreas()
{
return //Load data from an other source
}
}
Now when you have this setup repository could be easily testable for different behaviors of the context itself. This is just an example to demonstrate idea:
//Arrange
var context = new Mock<IAreaContext>();
context.Setup(m => m.GetAreas()).Verifiable();
var sut = new AreaRepository(context.Object);
//Act
var _ = sut.GetAll();
//Assert
context.Verify();
If you want to test just the base class, then I would create a unit test specific implementation of the class, and just provide any helper functions to test the protected ones. Basically what you have done with MyAreaRepository but as a private class within the test class.
I need to unit-test a virtual method defined in an abstract class. But the base class is abstract, so I can't create an instance of it. What do you recommend me to do?
This is a follow up to the following question: I am thinking about if it is possible to test via an instance of a subclass of the abstract class. Is it a good way? How can I do it?
There's no rule that says a unit test can't define its own classes. This is a fairly common practice (at least for me anyway).
Consider the structure of a standard unit test:
public void TestMethod()
{
// arrange
// act
// assert
}
That "arrange" step can include any reasonable actions (without side-effects outside of the test) which set up what you're trying to test. This can just as easily include creating an instance of a class whose sole purpose is to run the test. For example, something like this:
private class TestSubClass : YourAbstractBase { }
public void TestMethod()
{
// arrange
var testObj = new TestSubClass();
// act
var result = testObj.YourVirtualMethod();
// assert
Assert.AreEqual(123, result);
}
I'm not sure what your abstract class looks like, but if you have something like:
public abstract class SomeClass
{
public abstract bool SomeMethod();
public abstract int SomeOtherMethod();
public virtual int MethodYouWantToTest()
{
// Method body
}
}
And then, as #David suggested in the comments:
public class Test : SomeClass
{
// You don't care about this method - this is just there to make it compile
public override bool SomeMethod()
{
throw new NotImplementedException();
}
// You don't care about this method either
public override int SomeOtherMethod()
{
throw new NotImplementedException();
}
// Do nothing to MethodYouWantToTest
}
Then you just instantiate Test for your unit test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
SomeClass test = new Test();
// Insert whatever value you expect here
Assert.AreEqual(10, test.MethodYouWantToTest());
}
}
Using xUnit.net, it is possible for a Theory to have its MemberData originate from a derived class?
public abstract class BaseTest
{
public abstract IEnumerable<object[]> Data();
[Theory]
[MemberData(nameof(Data))]
public void TestData(string expected, string actual)
{
// assert goes here
}
}
public class ComplexTest : BaseTest
{
public override IEnumerable<object[]> Data()
{
// data goes here
}
}
The code above results in the following error message:
System.NotSupportedException : Specified method is not supported.
Another way of doing this (and IMO cleaner), is to put your test scenarios in their own specific classes and just define each scenario set as a separate MemberData attribute:
public class BaseTest
{
[Theory]
[MemberData(nameof(TestScenarios1.Data), MemberType = typeof(TestScenarios1)]
[MemberData(nameof(TestScenarios1.MoreData), MemberType = typeof(TestScenarios1)]
[MemberData(nameof(TestScenarios2.DifferentData), MemberType = typeof(TestScenarios2)]
public void TestData(string expected, string actual)
{
// assert goes here
}
}
public class TestScenarios1
{
public static IEnumerable<object[]> Data()
{
// data goes here
}
public static IEnumerable<object[]> MoreData()
{
// data goes here
}
}
public class TestScenarios2
{
public static IEnumerable<object[]> DifferentData()
{
// data goes here
}
}
As far as I know, this is not possible. MemberData's data is required to be static, therefore the data must originate from its own class.
public static IEnumerable<object[]> Data()
{
// data goes here
}
[Theory]
[MemberData(nameof(Data))]
public void TestData(string expected, string actual)
{
// assert goes here
}
You're correct in your answer. Posting this non-answer in case it happens to spark an idea.
MemberData can be passed params, which might help depending on your specific scenario?
Other than that, the best you can prob do is to put a forwarder:
public abstract class BaseTest
{
protected void RunTest(string expected, string actual)
{
Assert.Equal(expected, actual);
}
}
public class ComplexTest : BaseTest
{
static IEnumerable<object[]> Data() =
{
{ "a", "a" }
}
[Theory, MemberData(nameof(Data))]
void TestData(expected, actual) => base.RunTest(expected, actual);
}
Another way is to add MemberData only to derived class.
It will check members by name and take the correct one from the current class.
The only thing that analyzer with warn that you must specify member in base class (that by default treated as an error), so you have to disable this rule. If you try to specify this method in both classes - base and derived only base classes would be used.
The issue about analyzer described in xunit github: https://github.com/xunit/xunit/issues/1243
Your example may look:
public abstract class BaseTest
{
[Theory]
#pragma warning disable xUnit1015 // MemberData must reference an existing member
[MemberData(nameof(Data))]
#pragma warning restore xUnit1015 // MemberData must reference an existing member
public void TestData(string expected, string actual)
{
// assert goes here
}
}
public class ComplexTest : BaseTest
{
public static IEnumerable<object[]> Data()
{
return data;
// data goes here
}
}
Doing TDD and want to isolate the method under test: Direct();
However, when the test creates MyClass, SomeClass.SetupStuff(); blows up (NotImplementedException). So, modified the IMyClass interface to have a Configure(); method that can be called after MyClass construction to avoid the exception.
Question: Is this an accepted way of handling this scenario or is there some basic OOP principal that this breaks?
public class MyClass : IMyClass
{
public MyClass()
{
// class with static method that sets stuff up
SomeClass.SetupStuff();
}
public void IMyClass.Direct()
{
// want to test this
}
}
vs
public class MyClass : IMyClass
{
public MyClass()
{
}
public void IMyClass.Direct()
{
// want to test this
}
//
public void IMyClass.Configure()
{
// class with static method that sets stuff up
SomeClass.SetupStuff();
}
}
One way to avoid such problems is to use dependency injection
public class MyClass : IMyClass
{
public MyClass(ISomeClass someClass)
{
someClass.SetupStuff();
}
public void IMyClass.Direct()
{
// want to test this
}
}
By decoupling your class from SomeClass, you are free to provide a mock implementation of ISomeClass during test and can provide a full implementation at runtime.
I'm using the Unity dependency injection framework.
I have two classes, that each take the same delegate parameter in the constructor. Each class should get a different method when resolved.
Can I set this up without using attributes ? If not how would you do it with attributes?
Yep, you can decorate properties or constructor parameters with the [Dependency] attribute.
This example isn't using delegates, it's just using an interface instead, but it shows two of the same interface being registered with different names, and a class requesting a particular one in its constructor:
[TestClass]
public class NamedCI
{
internal interface ITestInterface
{
int GetValue();
}
internal class TestClassOne : ITestInterface
{
public int GetValue()
{
return 1;
}
}
internal class TestClassTwo : ITestInterface
{
public int GetValue()
{
return 2;
}
}
internal class ClassToResolve
{
public int Value { get; private set; }
public ClassToResolve([Dependency("ClassTwo")]ITestInterface testClass)
{
Value = testClass.GetValue();
}
}
[TestMethod]
public void Resolve_NamedCtorDependencyRegisteredLast_InjectsCorrectInstance()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ITestInterface, TestClassOne>("ClassOne");
container.RegisterType<ITestInterface, TestClassTwo>("ClassTwo");
container.RegisterType<ClassToResolve>();
var resolvedClass = container.Resolve<ClassToResolve>();
Assert.AreEqual<int>(2, resolvedClass.Value);
}
}
[TestMethod]
public void Resolve_NamedCtorDependencyRegisteredFirst_InjectsCorrectInstance()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ITestInterface, TestClassTwo>("ClassTwo");
container.RegisterType<ITestInterface, TestClassOne>("ClassOne");
container.RegisterType<ClassToResolve>();
var resolvedClass = container.Resolve<ClassToResolve>();
Assert.AreEqual<int>(2, resolvedClass.Value);
}
}
}
Instead, you could try passing a factory in on the constructor of the objects. That way you can guarantee (and test) in code exactly what objects are created.