Reputation: 267
I have an interface that is implemented in multiple classes. That interface has a method which returns a bool and I'm trying to mock that method so that it always returns true for unit testing purposes.
Example:
public interface IBase
{
}
public interface IParent
{
bool IsValid(int number);
ChildTypeEnum Type { get; }
}
public class A: IBase, IParent
{
public bool IsValid(int number){...}
ChildTypeEnum Type { get { return ...; } }
//other methods
}
public class B: IBase, IParent
{
public bool IsValid(int number){...}
ChildTypeEnum Type { get { return ...; } }
//other methods
}
public class C: IBase, IParent
{
public bool IsValid(int number){...}
ChildTypeEnum Type { get { return ...; } }
//other methods
}
public class D: IBase
{
//other methods
}
Is there any way to mock the IParent.IsValid() method so that I can invoke the mocked method when trying to test the ChildsEngine.ValidateParent() method?
public class ChildsEngine
{
private readonly IChildsLoader childsLoader;
//Constructor for mocking
public ScheduleRulesEngine(IChildsLoader childsLoader)
{
this.childsLoader = childsLoader;
}
public ParentValidation ValidateParent(int number, List<ChildTypeEnum> filterChilds = null)
{
var invalidChilds = new List<ChildTypeEnum>();
var childs = childsLoader.Childs.OfType<IParent>();
if (filterChilds != null)
childs = childs.Where(x => filterChilds .Contains(x.Type)).ToList();
foreach (var child in childsLoader)
{
if (!child.IsValid(number))
{
invalidChilds.Add(child.Type);
}
}
return new ParentValidation (invalidChilds);
}
}
Some extra information:
The only "hack" that I've found is to set the IsValid method as virtual on the child classes, but this forces me to mock the concrete class instead of the interface, meaning that my tests are susceptible to changes if the constructor of the classes suffers changes.
Upvotes: 0
Views: 3168
Reputation: 23224
With Moq
you can mock the interface directly.
var parent1 = new Mock<IParent>();
parent1.Setup(m => m.IsValid(It.IsAny<Int32>())).Returns(true);
var parent2 = new Mock<IParent>();
parent2.Setup(m => m.IsValid(It.IsAny<Int32>())).Returns(true);
List<IParent> parents = new List<IParent> { parent1.Object, parent2.Object };
Boolean testResult = ValidateParent(parents, 123);
Edit
In response to your comment below, where the list has to be a List<IBase>
.
With Moq
an interface can be implemented dynamically.
var parent1 = new Mock<IParent>();
parent1.Setup(m => m.IsValid(It.IsAny<Int32>())).Returns(true);
IBase base1 = parent1.As<IBase>().Object; // Implement the IBase interface.
var parent2 = (new Mock<IParent>());
parent2.Setup(m => m.IsValid(It.IsAny<Int32>())).Returns(true);
IBase base2 = parent2.As<IBase>().Object;
List<IBase> bases = new List<IBase> { base1, base2 };
Boolean testResult = ValidateParent(bases, 123);
Console.WriteLine(testResult);
Upvotes: 0
Reputation: 52240
Why wouldn't you just stub the interface?
public Stub : IParent, IBase
{
public bool IsValid(int number) { get { return true; } }
}
//Arrange
var list = Enumerable.Range(1,10).Select(
i => new Stub() as IBase
).ToList();
var o = new ClassUnderTest();
//Act
var result = o.ValidateParent(list, 7);
//Assert
Assert.IsTrue(result);
Upvotes: 1