3

我注意到,为了对我的 OO 代码中的每个单元进行单元测试,我需要将访问修饰符设置为 public,即使在应该受到保护的方法上,或者可能是私有的。这是好的做法吗?

public class EnforceBusinessRules
{
    BusinessState m_state;

    public EnforceBusinessRules()
    {
        m_state = START;
    }


    public bool isInputcurrentlyFormatted(string input)
    {
        //code goes here to ensure the input passes formatting test
        //modify m_state appropriately
    }


    public bool InputContainsValidStartAndEndTokens(string input)
    {
        //code goes here to ensure that the start and end tokens of the input are of the type available in the system
        //modify m_state appropriately
    }


    public bool StartEndCommandisValidAccordingtoCurrentSystemSettings(string input)
    {
        //code goes here to check the start and End codes match the current start and end codes for the day
        //modify m_state appropriately
    }

    // and so on 
}
4

6 回答 6

6

单元测试是“黑盒”测试。您应该只测试外部可见的元素。如果您测试所有内部工作,那么您将无法在不修改所有单元测试的情况下正确重构代码。

于 2012-06-03T12:52:32.580 回答
1

如果您发现需要更改访问修饰符,因为您需要测试私有成员中的大量代码,这可能表明您的类太大。考虑将您想要测试的行为分解为具有您可以测试的公共接口的较小类。您的代码可能受到上帝目标代码气味的影响。

请记住,受保护成员与公共成员非常相似,只是可能的客户端空间要小得多(仅限派生类)。您可以考虑通过创建仅您的测试使用的派生对象来对这些方法进行单元测试。这样,您将以与客户使用它们相同的方式测试这些方法。

这是您可以修改代码的一种方法:

public class EnforceBusinessRules
{
    BusinessState m_state;

    public EnforceBusinessRules(IEnumerable<Rule> rules)
    {
        m_state = START;
    }

    public void Enforce(string input)
    {
        foreach (var rule in rules)
        {
            m_state = rule.EnforceRule(input);
        }
    }
}

public interface Rule
{
    public BusinessState EnforceRule(string input);
}

public class IsInputcurrentlyFormatted : Rule
{
    public BusinessState EnforceRule(string input)
    {
        //code goes here to ensure the input passes formatting test
    }
}

public class InputContainsValidStartAndEndTokens : Rule
{
    public BusinessState EnforceRule(string input)
    {
        //code goes here to ensure the input passes formatting test
    }
}

public class StartEndCommandisValidAccordingtoCurrentSystemSettings : Rule
{
    public BusinessState EnforceRule(string input)
    {
        //code goes here to ensure the input passes formatting test
    }
}

// and so on
于 2012-06-03T13:00:19.707 回答
0

如果您需要测试私有或受保护的属性或方法,那么您应该将功能提取到单独的类中。每个班级应该只做一件事(单一职责原则)。奇怪的是,您的私有方法在您的课程的主要目的上执行次要功能。

提取后,会发生两件好事:首先,您希望测试的代码现在可以通过单元测试完全访问。其次,您不必在 EnforceBusinessRules 类中担心它。

于 2012-06-04T07:49:38.147 回答
0

通常,向外界公开您不想公开的方法/类/属性/任何东西都是不好的做法。我们在我工作的地方遇到了类似的问题。我们编写了针对公共方法和属性的测试,因为这些公共方法在某些时候应该调用所有私有方法。如果您有内部类/属性/方法,您可以使用InternalsVisableTo单元测试库可访问的属性。

[assembly: InternalsVisibleTo("AssemblyB")]

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

于 2012-06-03T13:02:44.577 回答
0

听起来您未能创建 getter 和 setter 方法以便正确封装您的私有数据。

单元测试应该通过 getter 和 setter 访问数据。

避免在类代码中实例化协作对象,而是注入这些依赖项。

于 2012-06-03T13:04:54.497 回答
0

不。在我看来,你想错了。你可以在不公开事情的情况下推断事情。例如,可以通过函数返回来实现属性的值。

在受保护成员的情况下。问问你自己这意味着什么。这意味着派生类可以访问该成员。所以在测试中创建一个派生类型。

于 2012-06-03T12:54:58.360 回答