测试抽象类中使用的方法

发布于 2024-08-28 15:52:08 字数 1117 浏览 5 评论 0原文

我必须对一个方法 (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()

I have to Unit Test a method (runMethod()) that uses a method from an inhereted abstract class to create a boolean. The method in the abstract class uses XmlDocuments and nodes to retrieve information. The code looks somewhat like this (and this is extremely simplified, but it states my problem)

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
    }
}
}

So, the code wants to get a property from a created XmlDocument and uses it to form the result to a boolean. Now my question is, what is the best solution to make sure I have control over the booleans result behaviour. I'm using Moq for possible mocking.

I know this code example is probably a bit fuzzy, but it's the best I could show. Hope you guys can help.

EDIT: What I basically need is:
I need to be able to control getProperty() while im testing the AbstractInheret class

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

感情废物 2024-09-04 15:52:08

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

Since the value of the boolean is controlled by the xml, you could refactor your code, so you can easily set the xml.

Like this:

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
        }
    }
}

This way you don't have to mock anything and you could easily pass a string of xml to your class. You should also check for error condition involving not valid xml passed to the constructor.

铁轨上的流浪者 2024-09-04 15:52:08

我不太确定你这个问题到底是什么意思 -

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

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

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

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

I am not very sure what exactly you mean by this question -

"what is the best solution to make sure I have control over the booleans result behaviour."

I am guessing that you need the boolean value of a property. So, this might just do!

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

Just plug it in code and it should be good. :)

娇柔作态 2024-09-04 15:52:08

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

If I understand your question correctly, you want to know how to control the result of getProperty so that you can test addIfContains with different boolean values.

If you are having difficulty writing a test for something, it often means you are trying to test too much, or that there is a problem with the design of the code.

You might be able to make this code more testable by avoiding the use of inheritance. As you have discovered, inheritance is often hard to handle in unit tests (there is a lot of tight-coupling going on), and delegation usually works better anyway. I'd recommend making the following change to the design:

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
      }
    }
}

Then you can easily mock out PropertyManager.

If your design requires that you use an abstract base class (for other functions other than just getProperty), you can still use the delegate approach:

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
      }
    }
}
大姐,你呐 2024-09-04 15:52:08

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

If for some reason you cannot refactor your code in the way described in my first answer (such as a third party is providing the abstract base class), then you can create a subclass of AbstractInherit that overrides just the getProperty method. Note that I really don't like that type of approach, as it couples your tests to the internal implementation of the class. But sometimes you have no choice.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文