我不确定我想做什么是可能的。我有一个看起来像这样的界面:
public interface IObject
{
void MethodA(ObjectA arg1);
void MethodB(ObjectB arg1, ObjectC arg2);
void MethodC(ObjectD arg1, ObjectE arg2);
}
我有类似下面的实现:
public class ObjectImplementation : IObject
{
public void MethodA(ObjectA arg1)
{
if(arg1.Something)
{
MethodB(new ObjectB(arg1), new ObjectC(arg1));
}
else
{
MethodC(new ObjectD(arg1), new ObjectE(arg1));
}
}
}
我正在尝试编写一个单元测试来测试是否根据我的条件调用了对methodB或methodC的调用。如何实现这样的目标?
答案 0 :(得分:2)
您正在尝试模拟接口并验证此接口的实现。
您可以将方法C和D设为虚拟,并在模拟中使用实现。
<强>实施强>
public class ObjectImplementation : IObject
{
public void MethodA(ObjectA arg1)
{
if (arg1.Something)
{
MethodB(new ObjectB(arg1), new ObjectC(arg1));
}
else
{
MethodC(new ObjectD(arg1), new ObjectE(arg1));
}
}
public virtual void MethodB(ObjectB arg1, ObjectC arg2)
{
}
public virtual void MethodC(ObjectD arg1, ObjectE arg2)
{
}
}
<强>测试强>
[Fact]
public void Test_WhenSomethingIsTrue_MethodB_Invoked_WithObjects_B_And_C()
{
// Arrange
Mock<ObjectImplementation> mockObject = new Mock<ObjectImplementation>();
ObjectA arg = new ObjectA();
arg.Something = true;
// Act
mockObject.Object.MethodA(arg);
// Assert
mockObject.Verify(o => o.MethodB(It.Is<ObjectB>(b=> b.Arg == arg), It.Is<ObjectC>(c => c.Arg == arg)));
}
[Fact]
public void Test_WhenSomethingIsFalse_MethodC_Invoked_WithObjects_D_And_E()
{
// Arrange
Mock<ObjectImplementation> mockObject = new Mock<ObjectImplementation>();
ObjectA arg = new ObjectA();
arg.Something = false;
// Act
mockObject.Object.MethodA(arg);
// Assert
mockObject.Verify(o => o.MethodC(It.Is<ObjectD>(d => d.Arg == arg), It.Is<ObjectE>(e => e.Arg == arg)));
}
答案 1 :(得分:0)
为什么你不能简单地假装那个方法存根
Mock<IObject> m = new Mock<IObject>();
m.Setup(x => s.MethodB(new ObjectB(arg1), new ObjectC(arg1)))
.Callback(() => Console.WriteLine("MethodB Called"));
因此,如果您的条件if(arg1.Something)
满足,那么将会调用被模拟的条件,您将知道
答案 2 :(得分:0)
虽然接受的解决方案应该有效,但我强烈建议您不要进行此类测试。每个方法调用都会产生一些输出和一些副作用。因此,如果没有输出且没有副作用,那么方法根本不做任何事情。通过声明调用哪个MethodB或MethodC,您不会检查MethodA的输出,也不会检查它的副作用。这些测试很脆弱,因为它们只测试MethodA的一个可能的实现,而不是它实际上做的。脆弱我的意思是:
假设您有以下IObject实现
class ObjectImpl
{
public void MethodA(ObjectA arg1)
{
if (arg1.Something)
{
MethodB(new ObjectB(arg1), new ObjectC(arg1));
}
else
{
MethodC(new ObjectD(arg1), new ObjectE(arg1));
}
}
public void MethodB(ObjectB arg1, ObjectC arg2)
{
Console.WriteLine("Hi {0} and {1}", arg1, arg2);
}
public void MethodC(ObjectD arg1, ObjectE arg2)
{
Console.WriteLine("Bye {0} and {1}", arg1, arg2);
}
}
因此,基本上MethodA只是打印&#34;嗨&#34;或者&#34;再见&#34;到控制台。然后,如果有人会注意到MethodB和MethodC在MethodA之外的任何地方都没有使用过,他可能会删除它们。请注意,MethodA仍然是相同的,因此除了测试之外什么都不会被破坏。
class ObjectImpl
{
// Everything works as before except broken build
public void MethodA(ObjectA arg1)
{
if (arg1.Something)
{
Console.WriteLine("Hi {0} and {1}", new ObjectB(arg1), new ObjectC(arg1));
}
else
{
Console.WriteLine("Bye {0} and {1}", new ObjectD(arg1), new ObjectE(arg1));
}
}
}