Тестирование двух зависимых классов в C # - PullRequest
1 голос
/ 15 июля 2011

Проблема, которую я хочу решить, состоит в том, как протестировать два зависимых класса в C #.Для тестирования я использую NUnit и Moq.

Допустим, у меня есть пользовательская коллекция, которая автоматически нумерует ее элементы.Значения внутри коллекции должны храниться в ее первоначальном порядке, поэтому она должна быть пересчитана.В следующем коде показан самый простой пример упомянутых классов:

public interface ICustomItem
{
    int Id { get; set; }
    ICustomCollection<ICustomItem> ParentCollection { get; set; }
}

public interface ICustomCollection<T> where T : ICustomItem
{
    IEnumerable<T> Items { get; set; }
    void Add(T t);
    // And more of course...
}

public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem
{
    public IEnumerable<T> Items { get; set; }

    public void Add(T t)
    {
        // Some logic here...
        t.Id = Items.Count(); // Generate Id
    }
}

При добавлении элемента в коллекцию генерируется новый Id и присваивается CustomItem.Механизм автоумерации должен быть включен и в другие методы, такие как Remove (), но для этого вопроса я оставил только метод Add.

Вопрос в том, как проверить, работает ли автоумерация правильно?Когда макет передается как параметр, он не изменяется внутри класса.Должен ли я тестировать класс с простым экземпляром класса CustomItem, созданного для тестов?

tl; dr

Другими словами, я хочу иметь возможность изменятьиздеваться внутри класса.

Ответы [ 3 ]

1 голос
/ 15 июля 2011

Попробуйте использовать класс в тесте так же, как вы используете его из производственного кода.Это даст вам самый удобный тест в том смысле, что вы можете свободно рефакторировать код внутри классов, не нарушая и даже не меняя тест.Тест также послужит примером того, как использовать класс.

Для начала я бы не использовал Moq, а вместо этого использовал бы короткий класс MockCustomItem, который вы реализуете только для теста.

Затем добавьте несколько значений и подтвердите, что вы ожидаете получить результат.Сделайте привычкой использовать только одно утверждение в каждом тесте, как показано ниже.

[TestFixture]
public class GivenCustomCollectionWithTwoElements
{
    private CustomCollection<MockCustomItem> _customCollection;

    [SetUp]
    public void SetUp()
    {
        _customCollection = new CustomCollection<MockCustomItem>();

        _customCollection.Add(new MockCustomItem());
        _customCollection.Add(new MockCustomItem()); 
    }

    [Test]
    public void CheckLength()
    {
        Assert.That(_customCollection.Items, Is.EqualTo(2));
    }

    [Test]
    public void CheckFirstItemId()
    {
        Assert.That(_customCollection.Items.ElementAt(0).Id, Is.EqualTo(0));
    }

    [Test]
    public void CheckSecondItemId()
    {
        Assert.That(_customCollection.Items.ElementAt(1).Id, Is.EqualTo(1));
    }

    private class MockCustomItem : ICustomItem
    {
        public int Id { get; set; }
        public ICustomCollection<ICustomItem> ParentCollection { get; set; }
    }

}

Как только вы это освоите, вы также можете использовать Moq для создания более кратких тестов с меньшим количеством стандартного кода.В этом случае также могут использоваться NUnit параметризованные тестовые случаи.

1 голос
/ 15 июля 2011

В модульных тестах вы должны тестировать только тот модуль, который тестируете прямо сейчас.Так что я бы сказал, что вы должны смоделировать / подделать ICustomItem, отправить его внутрь, а затем посмотреть, получит ли поддельный объект тот идентификатор, который вы ожидаете.

Прочтите мой ответ здесь для получения дополнительной информации по той же теме ЛюбойПриложения ASP.NET (WebForm), которые имеют хорошие модульные тесты (CodePlex или где-либо еще)?

Я использую FakeItEasy в качестве mock / fake-framework, но я думаю, что moq будет выглядеть примерно так, вот мой код дляit

[TestFixture]
public class CustomCollectionTests{

    [Test]
    public void Add_AddTwoItems_ItemsGetsConsecutiveIds() {
        var customItem1 = A.Fake<ICustomItem>();
        var customItem2 = A.Fake<ICustomItem>();
        var cutomCollection = new CustomCollection<ICustomItem>();
        cutomCollection.Add(customItem1);
        cutomCollection.Add(customItem2);
        Assert.AreEqual(1, customItem1.Id);
        Assert.AreEqual(2, customItem2.Id);
    }
}


public interface ICustomItem {
    int Id { get; set; }
}

public interface ICustomCollection<T> where T : ICustomItem {
    void Add(T t);
}

public class CustomCollection<T> : ICustomCollection<T> where T : ICustomItem {
    public List<T> innerList = new List<T>();

    public void Add(T t) {
        // Some logic here...
        innerList.Add(t);
        t.Id = innerList.Count(); // Generate Id
    }
}

Редактировать

Удален непроверенный пример MOQ, который, похоже, не работает.

0 голосов
/ 15 июля 2011

Вы правы в том, что макет не изменен. Но вы должны иметь возможность проверить макет после вызова метода add следующим образом:

mock.VerifySet(x => x.Id = 42);

Не забудьте установить что-либо в свойстве Items перед вызовом Add. Это что-то должно вернуть 42 при запросе Count (). Это также может быть насмешкой.

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