Тестирование метода, используемого из абстрактного класса - PullRequest
0 голосов
/ 14 апреля 2010

Мне нужно протестировать метод (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 для возможного насмешки.

Я знаю, что этот пример кода, возможно, немного нечеткий, но это лучшее, что я мог показать. Надеюсь, вы, ребята, можете помочь.

РЕДАКТИРОВАТЬ: Что мне в основном нужно, это:
Мне нужно иметь возможность управлять getProperty () во время тестирования класса AbstractInheret

Ответы [ 4 ]

1 голос
/ 15 апреля 2010

Поскольку значение логического значения контролируется 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, переданным в конструктор.

0 голосов
/ 15 апреля 2010

Если по какой-то причине вы не можете реорганизовать свой код способом, описанным в моем первом ответе (например, третья сторона предоставляет абстрактный базовый класс), то вы можете создать подкласс AbstractInherit, который переопределяет только метод getProperty. Обратите внимание, что мне действительно не нравится такой подход, поскольку он связывает ваши тесты с внутренней реализацией класса. Но иногда у тебя нет выбора.

0 голосов
/ 14 апреля 2010

Я не совсем уверен, что именно вы подразумеваете под этим вопросом -

«Как лучше всего убедиться, что у меня есть контроль над поведением логических результатов».

Я предполагаю, что вам нужно логическое значение свойства. Так что это может просто сделать!

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

Просто включите его в код, и это должно быть хорошо. :)

0 голосов
/ 14 апреля 2010

Если я правильно понимаю ваш вопрос, вы хотите знать, как контролировать результат 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
      }
    }
}
...