简体   繁体   English

单元测试时使用反射或属性?

[英]Use reflection or a property when unit testing?

This is a class I'm a bit concerned about. 这是我有点担心的课程。 My goal is to unit test the addresses list: 我的目标是对地址列表进行单元测试:

public class LabelPrinter
{
    private readonly IEnumerable<Address> _addresses;

    public LabelPrinter(IEnumerable<Address> addresses)
    {
        _addresses = addresses;
    }

    public Document Create()
    {
        // ... Generate PDF, etc ...
    }
}

So what is best: 什么是最好的:

  1. Use reflection to inspect the private property, or 使用反射检查私有财产,或
  2. Since the original IEnumerable can be modified from outside anyway, make a public getter and test it instead? 既然原来的IEnumerable可以从外面修改,那么做一个公共的getter并测试它呢?

In general, private members shouldn't be unit tested, since anything the class is doing with it's private members should somehow be reflected in the externally testable behavior of the object. 一般来说,私有成员不应该进行单元测试,因为类的私有成员所做的任何事情都应该以某种方式反映在对象的外部可测试行为中。 In other words, who cares what's going on in there, as long as its external behavior is what it should be. 换句话说,谁在乎那里发生了什么,只要它的外在行为是应该的。

Unit testing private members also couples your tests to the internals of a class, making them more brittle. 对私人成员进行单元测试也会将您的测试与课堂内部相结合,使其更加脆弱。 If you decide to use a more efficient collection later down the road, your tests will break, even though the behavior of the object hasn't changed. 如果您决定稍后使用更高效的集合,即使对象的行为没有改变,您的测试也会中断。 You especially want to avoid reflection, since looking up properties by name means your tests break if the property name ever changes. 您尤其希望避免反射,因为按名称查找属性意味着如果属性名称发生更改,则测试会中断。

In other words - if you need to test the Address class, do it from its own unit tests, rather than from the LabelPrinter 's tests. 换句话说 - 如果你需要测试Address类,可以从它自己的单元测试中进行,而不是从LabelPrinter的测试中进行。 If you must use one of your two methods, use the second one, rather than reflection. 如果必须使用两种方法中的一种,请使用第二种方法,而不是反射。

What are you trying to test about the addresses list here? 你想在这里测试一下addresses列表? In the example code you've provided above your job is actually rather easy because you can inject the list through your constructor. 在上面提供的示例代码中,您的工作实际上非常简单,因为您可以通过构造函数注入列表。 So in your tests you can access the list as such and therefore don't necessarily need to expose it again: 因此,在您的测试中,您可以访问列表,因此不一定需要再次公开它:

[Test]
public void Test()
{
    IEnumerable<Address> addresses = new List<Address>();
    LabelPrinter printer = new LabelPrinter(addresses);

    ... // execute your test here

    Assert.AreEqual(blah, addresses.get(0));
    // or any other assertion you want to make on the addresses list
    // created up above.
}

Particularly while learning unit testing, concerns about keeping fields private are trumped by easy testing and better coverage. 特别是在学习单元测试时,通过简单的测试和更好的覆盖范围来避免对保持字段保密的担忧。 Option 2. 选项2。

Test Create and not the setter (which is effectively what you have here). 测试Create而不是设置器(这实际上是你在这里)。 I find testing setters/getters to be a bit of a waste of time. 我发现测试设置者/吸气剂有点浪费时间。 Esp. ESP。 as most of the time the setter will have to be executed for some other test to work. 因为大多数时候必须执行setter才能进行其他测试。 They are also for the most part too simple to fail. 它们在很大程度上也很容易失败。

So rather than validate that LabelPrinter has a _addresses and it is Y, check that the output of Create includes the relevant details. 因此,不要验证LabelPrinter是否具有_addresses并且它是Y,请检查Create的输出是否包含相关详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM