我正在编写一些单元测试,我需要能够断言是否根据设置数据调用了一个方法。
E.g。
String testValue = "1234";
MyClass target = new MyClass();
target.Value = testValue;
target.RunConversion();
// required Assertion
Assert.MethodCalled(MyClass.RunSpecificConversion);
然后会有第二个测试,其中testValue为null,我想声明该方法尚未被调用。
特定测试场景的更新:
我有一个代表从XML反序列化的信息的类。这个类包含了我需要转换成自己的类的一些信息。
XML类是关于某人的信息,包括帐户信息和不同字段中的一些电话号码。
我有一个从XML类创建Account类的方法,以及从XML类创建正确的手机类的方法。我对每种方法都进行了单元测试,但我想测试一下,当调用帐户转换时,它会运行电话转换,因为结果实际上是帐户类的属性。
我知道在输入正确的信息后我可以测试帐户类的属性,但是我已经嵌套了嵌套的属性,并且测试整个树可能变得非常麻烦。我想我可以让每个级别的测试都在它下面的下一个级别,但理想情况下我想确保调用正确的conversino方法并且代码在实现中没有重复。
答案 0 :(得分:1)
您可以使用Rhino Mocks或moq等模拟框架。您也可以使用像Isolator这样的隔离框架来实现这一目标。
另一个选择是继承要验证的类,并在其中引发一个调用该方法的标志。而不是在你的测试断言中断言反对该标志。 (基本上它是一个手动模拟)
使用隔离器的示例:
Isolate.Verify.WasCalledWithAnyArguments(() => target.RunSpecificConversion());
免责声明 - 我在Typemock工作
答案 1 :(得分:1)
答案 2 :(得分:1)
您想要研究模拟框架的使用。
或者您可以创建自己的假对象来记录呼叫。您需要创建该类实现的接口。
我见过的一种制作假货的方法如下:
interface MyInterface
{
void Method();
}
// Real class
class MyClass : MyInterface
{
}
// Fake class for recording calls
class FakeMyClass : MyInterface
{
public bool MethodCalled;
public void Method()
{
this.MethodCalled = true;
}
}
然后你需要使用一些依赖注入来运行测试时使用这个假类来代替真实类。
当然,问题在于Fake类只记录方法调用,但实际上并没有真正做任何事情。这并不总是适用。它在Model-View-Presenter环境中可以正常工作。
答案 3 :(得分:1)
另一个观点 - 你可能是在一个太低的单位测试,这可能会导致你的测试变得脆弱。
通常,最好测试业务需求而不是实现细节。例如您使用“1234”作为输入运行转换,并且转换应该反转输入,因此您希望“4321”作为输出。
请勿测试您希望通过特定步骤序列转换“1234”。将来您可能会更改实现细节,即使仍然满足业务要求,测试也会失败。
当然,您在问题中的测试可能是实际的业务需求,在这种情况下它是正确的。
当你想要这样做的另一种情况是,在真正的MyClass中调用转换不适合单元测试,即需要大量设置,或者是时间密集的。然后你需要模拟或存根。
回复问题编辑:
根据您的情况,我仍然倾向于通过检查输出进行测试,而不是检查是否调用了特定方法。
您可以使用不同的XML输入进行测试,以确保必须调用不同的转换方法才能通过测试。
我不会依赖测试来检查是否存在重复代码,而是在我遇到重复代码时重构代码,并且仅依靠单元测试来确保代码仍然执行相同的功能重构。