如何测试通过公共方法修改私有字段 [英] How to test private fields that are modified via public methods

查看:127
本文介绍了如何测试通过公共方法修改私有字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以指导我在那,它通过公用方法改性的一类测试私有字段的建议方法。我读过很多评论的人表明测试私有成员是不建议,因为它们内部的实现,但这种情况下的似乎的是从其他大多数答案不同。

我在想使私人领域的保护,创建一个测试子类,它暴露了现场,但如果我不能修改类的内部是什么?

在私有成员下面的示例code测试将_values​​这是一个只写经收集的AddValue()。

接收新的价值

 公共类样品
{

    私人字典<字符串,字符串> _values​​;
    私营的DateTime _created;

    公共样品()
    {
        _values​​ =新字典<字符串,字符串>();
        _created = DateTime.Now;
    }

    公共无效的AddValue(字符串键,字符串值)
    {
        _values​​.Add(键,值);
    }
}
 

解决方案

我认为这将是一个例子,其中的依赖注入可能的帮助。

这里发生的是,你要测试是否内部对象(字典 _values​​ )已正确更新通过调用的AddValue 。你可以通过注入一个模拟的字典到你的类在测试实现这一点。

这可以例如做如下。首先,你必须改变你的样品类一点点:

 公共类样品
{
    私人的IDictionary<字符串,字符串> _values​​ =新字典<字符串,字符串>();

    受保护的虚拟IDictionary的<字符串,字符串> GetDictionary()
    {
        返回this._values​​;
    }

    公共无效的AddValue(字符串键,字符串值)
    {
        GetDictionary()加(键,值)。
        // ^^^
        //注意到这一点!
    }
}
 

这现在允许你从你的样品类派生,并通过注入一个模拟的字典来替代默认的字典,另一个(您可以在您的测试设置观察)覆盖 InitializeDictionary 方法:

  //这个派生类只需要在您的测试项目:
内部类SampleTest:样品
{
    公共SampleTest(IDictionary的<字符串,字符串> dictionaryToUse)
    {
        this._dictionaryToUse = dictionaryToUse;
    }

    私人的IDictionary<字符串,字符串> _dictionaryToUse;

    保护覆盖的IDictionary<字符串,字符串> GetDictionary()
    {
        返回this._dictionaryToUse;
    }
}
 

在您的测试设置,现在就可以测试你的样品这个类的 SampleTest 类来代替。这应该是确定的,因为派生类是相同的除了的,它允许您指定将在内部使用的词典。单元测试检查的AddValue 现在看起来是这样的:

  [测试]
公共无效AddValue_addSomething_DictionaryHasOneAdditionalEntry()
{
    VAR mockDictionary =新字典<字符串,字符串>();
    变种样本=新SampleTest(mockDictionary);
    VAR oldCount = mockDictionary.Count;

    sample.AddValue(...);

    Assert.AreEqual(oldCount + 1,mockDictionary.Count);
}
 


<分> 免责声明:我绝不是一个单元测试的专家,所以我的例子可能是有缺陷的,甚至是太复杂了。我的目的是仅仅是为了证明你的可以的一类测试的内部属性,如果你设计你的类在一个合理的可检验的方式 - 例如,通过允许依赖注入的手段。

Can anyone guide me with a suggested means of testing a private field in a class that is modifed via a public method. I've read a lot of comments from people suggesting that testing private members is not advised as they are internal to the implementation, however this scenario seems to be different from most other answers.

I was thinking about making the private field protected and creating a test subclass that exposes the field but what if I couldn't modify the internals of the class?

In the sample code below the private member to test would be _values which is a write only collection receiving new values via AddValue().

public class Sample
{

    private Dictionary<string, string> _values;
    private DateTime _created;

    public Sample()
    {
        _values = new Dictionary<string, string>();
        _created = DateTime.Now;
    }

    public void AddValue(string key, string value)
    {
        _values.Add(key, value);
    }
}

解决方案

I think this would be an example where dependency injection might help.

What's happening here is that you want to test whether an internal object (the dictionary _values) was updated correctly by a call to AddValue. You could achieve this by injecting a mock dictionary into your class-under-test.

This could be done e.g. as follows. First, you'd have to change your Sample class a little bit:

public class Sample
{
    private IDictionary<string, string> _values = new Dictionary<string, string>();

    protected virtual IDictionary<string, string> GetDictionary()
    {
        return this._values;
    }

    public void AddValue(string key, string value)
    {
        GetDictionary().Add(key, value);
        //    ^^^
        // notice this!
    }
}

This now allows you to replace the default dictionary with another one (which you can observe in your test setup) by deriving from your Sample class and injecting a mock dictionary by overriding the InitializeDictionary method:

// this derived class is only needed in your test project:
internal class SampleTest : Sample
{
    public SampleTest(IDictionary<string, string> dictionaryToUse)
    {
        this._dictionaryToUse = dictionaryToUse;
    }

    private IDictionary<string, string> _dictionaryToUse;

    protected override IDictionary<string, string> GetDictionary()
    {
        return this._dictionaryToUse;
    }
}

In your test setup, you can now test this SampleTest class instead of your Sample class. This should be OK since the derived class is identical except that it allows you to specify the dictionary it will use internally. A unit test for checking AddValue could now look like this:

[Test]
public void AddValue_addSomething_DictionaryHasOneAdditionalEntry()
{
    var mockDictionary = new Dictionary<string, string>();
    var sample = new SampleTest(mockDictionary);
    var oldCount = mockDictionary.Count;

    sample.AddValue(...);

    Assert.AreEqual(oldCount + 1, mockDictionary.Count);
}


Disclaimer: I'm by no means a unit testing expert, so my example might be flawed or even be way too complicated. My intention was merely to demonstrate that you can test internal properties of a class if you design your class in a reasonably testable way -- e.g. by allowing the means of dependency injection.

这篇关于如何测试通过公共方法修改私有字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆