Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 测试从抽象类使用的方法_C#_Unit Testing_Mocking_Dependencies_Abstract - Fatal编程技术网

C# 测试从抽象类使用的方法

C# 测试从抽象类使用的方法,c#,unit-testing,mocking,dependencies,abstract,C#,Unit Testing,Mocking,Dependencies,Abstract,我必须对一个方法(runMethod())进行单元测试,该方法使用来自固有抽象类的方法来创建布尔值。抽象类中的方法使用XmlDocuments和节点来检索信息。代码看起来有点像这样(这是非常简化的,但它说明了我的问题) 因此,代码希望从创建的XmlDocument中获取属性,并使用它将结果形成布尔值。现在我的问题是,什么是确保我能控制布尔结果行为的最佳解决方案。我用最小起订量来模拟 我知道这个代码示例可能有点模糊,但这是我能展示的最好的例子。希望你们能帮忙 编辑:我基本上需要的是: 我需要能够在

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

因此,代码希望从创建的XmlDocument中获取属性,并使用它将结果形成布尔值。现在我的问题是,什么是确保我能控制布尔结果行为的最佳解决方案。我用最小起订量来模拟

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

编辑:我基本上需要的是:

我需要能够在测试AbstractInheret类时控制getProperty()

如果我正确理解了您的问题,您想知道如何控制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 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
      }
    }
}

我不太清楚你这个问题的确切意思-

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

我猜您需要属性的布尔值。所以,这可能就行了

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

只需将其插入代码,它就应该很好了。:)

由于布尔值由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的错误情况。

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

你的方法很有趣,吉姆:]我喜欢它,但不确定我是否能在实现中使用它。我试试看。如果成功,我会让你知道/接受你的答案。谢谢你的回复!我将替代方法移到另一个答案,以便清楚地知道您选择使用哪种解决方案。我还添加了一个示例,说明如何在使用委托的同时仍然使用抽象基类。我跟进了JJoos的示例,它提出了使用字典的解决方案。使用propertyName作为键,propertyValue作为值:]现在我不再使用getProperty(“键”),而是使用Dictionary[“key”]。谢谢你的反馈!它确实有帮助,但我必须为它重构许多代码>。获取布尔值不是问题:]问题是:我如何控制它的结果。由于依赖关系,我不能在测试中说:addIfContains=true或addIfContains=false。这就是我需要模拟/存根的地方。因此,我的问题是:当我的类使用从抽象类中继承的方法,并且使用未被注入的Xml依赖时,您如何处理这个问题。我恐怕无法理解您的问题。除非有更多关于“依赖性”和“需要模仿”的细节……好吧,我必须同意你的观点,我试图解释的情况也很难(而且很难在简单的上下文中解释)。但我基本上是在寻找吉姆提议的东西。当我测试AbstractInheret类“How”时,我需要能够控制getProperty(),您希望如何控制函数getProperty?接口/模拟还是通过重构。这仅用于单元测试目的
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
        }
    }
}