如何为poco对象创建测试

6

我是一名新手,想知道在测试时应该达到什么级别。例如,在我的代码中,我有以下对象:

public class RuleViolation
{
    public string ErrorMessage { get; private set; }
    public string PropertyName { get; private set; }

    public RuleViolation( string errorMessage )
    {
        ErrorMessage = errorMessage;
    }

    public RuleViolation( string errorMessage, string propertyName )
    {
        ErrorMessage = errorMessage;
        PropertyName = propertyName;
    }
}

这是一个比较简单的对象。所以我的问题是:

它需要单元测试吗?

如果需要,我应该测试什么以及如何测试?

谢谢


请查看我的更新,了解如何检查setter是否为私有。 - kemiller2002
5个回答

9

没有包含任何逻辑 => 没有需要测试的内容


4
我认为可能不需要。唯一需要验证的可能是访问修饰符,如果非常重要的话。
public string ErrorMessage { get; private set; }
public string PropertyName { get; private set; }

如果确实非常重要,希望类外的代码无法修改它们,那么这可能是我想要验证的唯一事情。

以下是如何获取属性中的访问器:

class Program
    {
        static void Main(string[] args)
        {
            var property = typeof(Test).GetProperty("Accessor");

            var methods = property.GetAccessors();
        }
    }



    public class Test
    {
        public string Accessor
        {

            get;
            private set;
        }    

    }

通过使用property.GetAccessors();,您可以查看是否存在setter。如果存在,则该setter是公共的。(还有属性IsPrivate和IsPublic可用于验证其他访问器)。

+1 这是一种随着代码演进而难以注意到的事情,而且测试起来非常简单,几乎没有理由不去测试。 - Cocowalla
你会如何测试类似这样的东西?因为你无法尝试去设置一个属性,它会显示编译器错误。或者我可能错过了一些简单的东西吗? - lancscoder
非常好的小测试!精简而迅速,正如我们所喜欢的一样!谢谢! - Will Marcouiller

1

你可以对这个对象进行单元测试,但它非常简单,不需要这样做。测试可能类似于(NUnit示例)

[Test]
public void TestRuleViolationConstructorWithErrorMessageParameterSetsErrorMessageProperty() {
    // Arrange
    var errorMessage = "An error message";

    // Act
    var ruleViolation = new RuleViolation(errorMessage);

    // Assert
    Assert.AreEqual(errorMessage, ruleViolation.ErrorMessage);
}

编写这样的测试没有太大的价值,因为您正在测试 .NET 框架的属性是否正常工作。通常情况下,您可以信任 Microsoft 已经做得很好了 :-)

关于模拟,当您的被测类有依赖关系时,例如依赖于应用程序中的另一个类或框架中的类型时,这将非常有用。模拟框架允许您调用依赖项上的方法和属性,而无需在代码中具体构建依赖项,而是允许您注入属性的定义值、方法的返回值等。Moq 是一个很棒的框架,一个带有依赖关系的基本类的测试看起来会像这样:

[Test]
public void TestCalculateReturnsBasicRateTaxForMiddleIncome() {
    // Arrange
    // TaxPolicy is a dependency that we need to manipulate.
    var policy = new Mock<TaxPolicy>();
    bar.Setup(x => x.BasicRate.Returns(0.22d));

    var taxCalculator = new TaxCalculator();

    // Act
    // Calculate takes a TaxPolicy and an annual income.  
    var result = taxCalculator.Calculate(policy.Object, 25000);

    // Assert
    // Basic Rate tax is 22%, which is 5500 of 25000.
    Assert.AreEqual(5500, result);
}  

TaxPolicy 应该在自己的 fixture 中进行单元测试以验证其是否正确。 在这里,我们想要测试 TaxCalculator 是否工作正常,因此我们模拟 TaxPolicy 对象以使我们的测试更简单;这样做,我们可以指定我们感兴趣的 TaxPolicy 部分的行为。 如果没有它,我们将需要创建手动编写的 mocks/stubs/fakes,或者创建真实的 TaxPolicy 实例来传递。

然而 Moq 的功能远不止于此,请查看 快速入门教程 以了解更多。


1

如果这是我的代码和我的对象,无论类有多简单或复杂,我都会为其编写测试,这是毋庸置疑的。即使该类似乎不太可能出现问题,测试也是您记录假设、设计决策和正确用法的地方。

通过这样做,您不仅可以验证您所拥有的内容是否按预期工作,而且还有机会思考典型情况(如果构造函数参数为空或以空格结尾会发生什么?为什么在不可变类中PropertyName是可选的?)。

如果(何时?)需求发生变化,您将有一个坚实的起点来解决这个问题。如果这个微不足道的类与所有其他类都不能很好地交互,您可能会有一个测试来捕捉到这一点,而不是让客户发现问题。

这只是正确的编写代码的方式。

希望对您有所帮助,
Berryl


0

即使是简单的构造函数,其中也有逻辑。我会进行测试:

RuleViolation ruleViolation = new RuleViolation("This is the error message");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.IsEmpty(ruleViolation.PropertyName);

RuleViolation ruleViolation = new RuleViolation("This is the error message", "ThisIsMyProperty");
Assert.AreEqual("This is the error message", ruleViolation.ErrorMessage);
Assert.AreEqual("ThisIsMyProperty", ruleViolation.PropertyName);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接