Вопрос о частном установщике модульного тестирования (C #) - PullRequest
7 голосов
/ 28 мая 2009

Я пытаюсь протестировать метод сущности Order под названием AddItem и пытаюсь убедиться, что дублирующиеся элементы не могут быть добавлены. Вот пример кода:

[Test]
public void ItemCannotBeAddedTwiceToOrder()
{
    Order o = new Order();
    Item i = new Item("Bike");

    o.AddItem(i);
    o.AddItem(i);

    Assert.AreEqual(o.ItemCount, 1, "A duplicate item was added.");
}

public void AddItem(Item newItem)
{
    if(!CheckForDuplicateItem(newItem))
       _items.Add(newItem);
}

public bool CheckForDuplicateItem(Item newItem)
{
    foreach(Item i in _items)
    {
        if(i.Id == newItem.Id)
          return true;
    }

    return false;
}

Итак, вот моя проблема: как установить идентификатор частного установщика нового элемента в методе test, чтобы метод CheckForDuplicateItem работал? Я не хочу делать этого члена публичным для хорошей практики кодирования, я полагаю. Я просто тупой и мне нужно, чтобы у сущности Item был открытый сеттер Id? Или мне нужно использовать отражение? Спасибо

Примечание - я использую NHibernate для персистентности

Ответы [ 5 ]

10 голосов
/ 28 мая 2009

Я обычно использую отражение для этой цели. Примерно так будет работать:

typeof(Item).GetProperty("Id").SetValue(i, 1, null);

где 1 - это идентификатор, который вы хотите установить для экземпляра newItem.

По моему опыту, вам редко нужно устанавливать Id, поэтому лучше просто оставить установщик закрытым. В тех немногих случаях, когда вам нужно установить Id для тестирования, просто используйте Reflection.

7 голосов
/ 28 мая 2009

Поскольку вы проверяете поведение своего Ордена, вы можете использовать фиктивные объекты в качестве его предметов. Используя фиктивные объекты, вы можете определить свои предположения о том, что произойдет с вашими фиктивными объектами, а также протестировать их. В этом случае вы можете определить два фиктивных объекта для каждого из элементов и ожидать, что будет вызван их метод получения идентификатора, и он возвратит уникальное значение. Затем вы можете проверить поведение Порядка и проверить, вызывается ли метод получения идентификатора элемента, как вы ожидали , Я рекомендую использовать Rhino Mocks от Ayende

4 голосов
/ 03 сентября 2016

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

var classWithPrivateSetters= new ClassWithPrivateSetters();
classWithPrivateSetters.SetPrivate(cwps => cwps.Number, 42);

Вставьте это в свою тестовую сборку, и все готово

public static class PrivateSetterCaller
{
    public static void SetPrivate<T,TValue>(this T instance, Expression<Func<T,TValue>> propertyExpression, TValue value)
    {
        instance.GetType().GetProperty(GetName(propertyExpression)).SetValue(instance, value, null);
    }

    private static string GetName<T, TValue>(Expression<Func<T, TValue>> exp)
    {
        MemberExpression body = exp.Body as MemberExpression;

        if (body == null)
        {
            UnaryExpression ubody = (UnaryExpression)exp.Body;
            body = ubody.Operand as MemberExpression;
        }

        return body.Member.Name;
    }
}
0 голосов
/ 30 мая 2009

Я думаю, вы можете здесь упустить смысл. Вы избегаете многократных добавлений, потому что не хотите многократных обращений к БД? Я думаю, что NHibernate дает вам это бесплатно. Или вы должны использовать набор? Каково значение для вызывающего абонента, что элемент может или не может быть добавлен?

Если проблема с постоянством отсутствует, вы можете просто добавить два разных элемента с одинаковым идентификатором и подтвердить, что у вас есть только первый. Должен быть какой-то способ определить, какие элементы находятся в порядке, или нет смысла добавлять их ...

0 голосов
/ 28 мая 2009

Другое решение состоит в том, чтобы сделать закрытые члены доступными, производным от класса и выставлением члена в производном классе. Это довольно много для тестирования, и Visual Studio имеет только встроенную поддержку для частных методов .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...