我在单元测试一个方法时遇到了麻烦,该方法改变了传递给它的引用类型的一些属性.
举个例子,假设我有一个名为Policy的类.
Policy policy = new Policy(); policy.Status = Active;
然后,我将此策略传递给策略管理器,以便取消激活策略.
policyManager.InactivatePolicy(policy);
inactivate策略方法执行以下操作:
public void InactivatePolicy(Policy policy) { policy.Status = Inactive; UpdatePolicy(policy); //saves the updated policy details via nhibernate }
我遇到的问题是单元测试这个DoSomething方法.(忽略它在这个例子中的作用是无用的这一事实)
public void DoSomething(Policy policy) { Policy policy = new Policy(); policy.Status = Active; policyManager.InactivatePolicy(policy); }
因为我模拟了策略管理器,所以状态不会被设置为非活动状态,因此当我断言在调用DoSomething之后策略的状态处于非活动状态时,由于它仍处于活动状态,因此测试失败.
[Test] public void TheStatusShouldBeInactiveWhenWeDoSomething() { MockpolicyManagerMock = new Mock (); MyClass mc = new MyClass(policyManagerMock.Object); Policy policy = new Policy(); policy.Status = Active; mc.DoSomething(policy); Assert.That(policy.Status, Is.EqualTo(Inactive)); //this fails }
所以我处在这样的情况下,代码在现实中工作,但在我的单元测试中被隔离.
我能够解决这个问题的唯一方法是让策略管理器的InactivatePolicy方法返回修改后的策略,以便我可以模拟预期的返回值.
public Policy InactivatePolicy(Policy policy) { policy.Status = Inactive; UpdatePolicy(policy); //saves the updated policy details via nhibernate return policy; } [Test] public void TheStatusShouldBeInactiveWhenWeDoSomething() { MockpolicyManagerMock = new Mock (); MyClass mc = new MyClass(policyManagerMock.Object); Policy expectedInactivePolicy = new Policy(); expectedInactivePolicy.Status = Inactive; Policy policy = new Policy(); policy.Status = Active; policyManagerMock .Setup(p => p.InactivatePolicy(policy)) .Returns(expectedInactivePolicy); mc.DoSomething(policy); Assert.That(policy.Status, Is.EqualTo(Inactive)); //this now succeeds }
通常情况下,当我努力进行单元测试时,这表明我做错了.
有谁知道这有更好的方法吗?是否一个人基本上被迫返回原本打算通过传递给方法的参考值更新的值?
我的问题可能是策略管理器不应该有一个InactivatePolicy方法,而应该是在Policy对象本身以及稍后调用的数据库更新?
您不应该嘲笑PolicyManager,您应该模拟UpdatePolicy方法,因为您仍然想要测试DoSomething方法的功能.
而且,你可能在树上测得太高了.
您应该单独测试InactivatePolicy()方法并仅测试该功能是否正常,然后再次在隔离中测试DoSomething()方法.
这里有2个独立的代码单元,你应该有单元测试来专门测试每个单元.