测试从抽象类使用的方法

时间:2010-04-14 11:56:05

标签: c# unit-testing mocking dependencies abstract

我必须对一个方法(runMethod())进行单元测试,该方法使用来自固有抽象类的方法来创建一个布尔值。抽象类中的方法使用XmlDocuments和节点来检索信息。代码看起来有点像这样(这非常简化,但它说明了我的问题)

namespace AbstractTestExample
{
public abstract class AbstractExample
{
    public string propertyValues;
    protected XmlNode propertyValuesXML;
    protected string getProperty(string propertyName)
    {
        XmlDocument doc = new XmlDocument();
        doc.Load(new System.IO.StringReader(propertyValues));
        propertyValuesXML= doc.FirstChild;

        XmlNode node = propertyValuesXML.SelectSingleNode(String.Format("property[name='{0}']/value", propertyName));
        return node.InnerText;
    }
}

public class AbstractInheret : AbstractExample
{
    public void runMethod()
    {
        bool addIfContains = (getProperty("AddIfContains") == null || getProperty("AddIfContains") == "True");
        //Do something with boolean
    }
}
}

因此,代码希望从创建的XmlDocument中获取属性,并使用它将结果形成为布尔值。现在我的问题是,确保我控制布尔结果行为的最佳解决方案是什么。我正在使用Moq进行嘲弄。

我知道这个代码示例可能有点模糊,但它是我能展示的最好的。希望你们能帮忙。

编辑:我基本上需要的是:
我需要能够在测试AbstractInheret类时控制getProperty()

4 个答案:

答案 0 :(得分:1)

由于布尔值是由xml控制的,因此您可以重构代码,这样就可以轻松设置xml。

像这样:

namespace AbstractTestExample
{
    public abstract class AbstractExample
    {
        protected XmlNode propertyValuesXML;

        protected string getProperty(string propertyName)
        {
            XmlNode node = propertyValuesXML.FirstChild.SelectSingleNode(String.Format("property[name='{0}']/value", propertyName));
            return node.InnerText;
        }
    }

    public class AbstractInheret : AbstractExample
    {
        public AbstractInheret(string propertyValues){

            propertyValuesXML = new XmlDocument();
            propertyValuesXML.Load(new System.IO.StringReader(propertyValues));
        }

        public void runMethod()
        {
            bool addIfContains = (getProperty("AddIfContains") == null || getProperty("AddIfContains") == "True");
            //Do something with boolean
        }
    }
}

这样你就不必模拟任何东西,你可以轻松地将一串xml传递给你的类。您还应检查传递给构造函数的无效xml的错误情况。

答案 1 :(得分:0)

如果我理解你的问题,你想知道如何控制getProperty的结果,以便你可以用不同的布尔值测试addIfContains。

如果您在为某些事情编写测试时遇到困难,通常意味着您尝试测试太多,或者代码设计存在问题。

您可以通过避免使用继承来使此代码更易于测试。正如您所发现的那样,继承通常很难在单元测试中处理(存在大量的紧耦合),并且委托通常也会更好地工作。我建议对设计进行以下更改:

namespace TestExample
{
    public interface PropertyManager {
      public string getProperty(string propertyName);
    }

    public class XmlPropertyManager: PropertyManager {
      public string getProperty(string propertyName) {
      //...xml parsing code here
      }
    }

    public class Example {
      private PropertyManager propertyManager;

      public void runMethod() {
        bool addIfContains = (propertyManager.getProperty("AddIfContains") == null || propertyManager.getProperty("AddIfContains") == "True");
        //Do something with boolean
      }
    }
}

然后你可以轻松地模拟出PropertyManager。

如果您的设计要求您使用抽象基类(对于除getProperty之外的其他函数),您仍然可以使用委托方法:

namespace TestExample
{
    public interface PropertyManager {
      public string getProperty(string propertyName);
    }

    public class XmlPropertyManager: PropertyManager {
      public string getProperty(string propertyName) {
      //...xml parsing code here
      }
    }

    public abstract class AbstractExample
    {
       protected PropertyManager propertyManager;

       //... other important methods
    }

    public class AbstractInheret: AbstractExample {

      public void runMethod() {
        bool addIfContains = (propertyManager.getProperty("AddIfContains") == null || propertyManager.getProperty("AddIfContains") == "True");
        //Do something with boolean
      }
    }
}

答案 2 :(得分:0)

我不太确定这个问题究竟是什么意思 -

  

“确保我控制布尔结果行为的最佳解决方案是什么。”

我猜你需要一个属性的布尔值。所以,这可能就是这样!

    public static bool GetBoolean(string boolStr)
    {
        bool bVal = default(bool);
        try
        {
            bVal = Convert.ToBoolean(boolStr);
        }
        catch (Exception) {
            bVal = default(bool);
        }
        return bVal;
    }

只需将其插入代码即可。 :)

答案 3 :(得分:0)

如果由于某种原因你无法以我的第一个答案中描述的方式重构你的代码(例如第三方提供抽象基类),那么你可以创建一个AbstractInherit的子类,它只覆盖getProperty方法。请注意,我真的不喜欢这种类型的方法,因为它将您的测试耦合到类的内部实现。但有时你别无选择。