我有一个在多个类中实现的接口。该接口有一个返回布尔值的方法,我正在尝试模拟该方法,以便为进行单元测试而始终返回true。
示例:
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
}
是否可以模拟IParent.IsValid()方法,以便在尝试测试ChildsEngine.ValidateParent()方法时可以调用模拟方法?
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);
}
}
一些额外的信息:
我发现的唯一“ hack”是在子类上将IsValid方法设置为虚拟方法,但这迫使我模拟具体的类而不是接口,这意味着如果类的构造函数会发生变化。
答案 0 :(得分:1)
您为什么不只对界面进行存根?
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);
答案 1 :(得分:0)
使用Moq
,您可以直接模拟接口。
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);
修改
为回应您在下面的评论,列表必须为List<IBase>
。
借助Moq
,可以动态实现接口。
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);