c# - 如何对期望通过引用更新对象的方法进行单元测试?

标签 c# unit-testing moq

我在对更改传递给它的引用类型的某些属性的方法进行单元测试时遇到问题。

举个例子,假设我有一个名为“Policy”的类。

Policy policy = new Policy();
policy.Status = Active;

然后,我将此策略传递给策略管理器以停用该策略。

policyManager.InactivatePolicy(policy);

停用策略方法执行以下操作:

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()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    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()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    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 方法,而应该在策略对象本身和稍后调用的数据库更新上?

最佳答案

您不应该模拟PolicyManager,而应该模拟UpdatePolicy 方法,因为您仍然想测试DoSomething 方法的功能。

此外,您可能在树上进行了过高的测试。

您应该单独测试 InactivatePolicy() 方法,并且仅测试功能是否正常工作,然后您应该再次在隔离中测试 DoSomething() 方法。

这里有 2 个独立的代码单元,您应该进行专门测试每个单元的单元测试。

关于c# - 如何对期望通过引用更新对象的方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1424854/

相关文章:

c# - 有没有更简洁的方法来在 C# 单元测试中 stub 值?

python - 是否有用于 Python 的类似 Spock 的测试库

java - 是否可以只运行一个测试类(利用 PowerMock 和 Mockito)?

c# - 模拟一个对其参数有副作用的方法

c# - 如何在 aspnetcore 身份中显示未经授权的消息

android - Robolectric - 无法加载类 : org. robolectric.shadows.ShadowMultiDex

c# - 模拟对象列表

c# - 你能从 StreamReader 对象中获取文件路径吗?

c# - asp.net 自定义控件属性依赖于另一个属性

c# - Rhino .OutRef 与 .Throw 不兼容?