Модульные тесты и база данных - PullRequest
3 голосов
/ 26 июня 2010

Этот вопрос о модульных тестах вызвал еще одну вещь, которая беспокоила меня. Я изучал три способа выполнения модульных тестов при попадании в базу данных.

  1. Создавайте фиктивные объекты и подключайте их. Преимущество этого состоит в том, что не требуется база данных, но это отнимает много времени, и я не уверен, какую отдачу от инвестиций я получаю. Я немного попал в МОК и МОК, но это все еще кажется болезненным.
  2. Создайте сценарии настройки и базы данных для создания известных случаев и протестируйте их. Опять же, это может занять много времени, но все же проще создавать, чем макетировать объекты большую часть времени. И другие люди на работе могут по-прежнему запускать его, предполагая, что на их локальном хосте есть SQL-сервер.
  3. Вручную проверьте базу данных dev и измените юнит-тесты. Интенсивная ручная работа, но если у меня есть «набор тестов», который не меняется, похоже, он работает нормально. На моей машине хотя бы :-).

Я знаю, что вариант 1 - это «правильный» способ выполнения модульных тестов, но из трех, это, вероятно, вариант, который я использовал меньше всего (хотя последние проекты были с МОК, так что дверь для меня открыта ). Я понимаю, что многое зависит от того, что именно высмеивается и что проверяется, но чего мне здесь не хватает?

Если контекст помогает, я нахожусь в магазине C #, пишу собственные приложения, всего несколько разработчиков.

Ответы [ 4 ]

3 голосов
/ 26 июня 2010

Первый не должен быть таким сложным, если у вас есть уровень доступа к данным, который предоставляет лишь несколько IQueryable<T> методов.Есть хороший трюк, который вы можете использовать для ложных данных: просто сохраняйте объекты сущностей в List<T> и используйте AsQueryable.Я считаю, что это проще, чем moq для частей данных.

Что касается IOC, я придерживаюсь позиции, что в настоящее время она используется чрезмерно (знайте, что мое мнение представляет меньшинство программистов в этом отношении).Вы можете использовать такой инструмент, как Moles во время тестирования, чтобы издеваться, не злоупотребляя дизайном вашей программы.Я не использую МОК, если дизайн не требует этого.

2 голосов
/ 26 июня 2010

Я бы определенно продолжал использовать настоящие юнит-тесты (вариант 1).Мне нравится совет Стивена для этого.

Вы также можете найти интеграционные тесты с реальной базой данных (вариант 2) , необходимые , чтобы использовать (вариант 2).Зачем?Поскольку часть того, что вам нужно протестировать (отображение O / R, совместимость с реальной схемой БД и т. Д.), Не охвачены настоящими модульными тестами.

Что касается логики настройки и разрыва, обычно достаточно наследования от этого(используя .NET, NUnit и SqlServer для базы данных):

using System.Transactions;
using NUnit.Framework;
namespace Crown.Util.TestUtil
{
    [TestFixture]
    public class PersistenceTestFixture
    {
        public TransactionScope TxScope { get; private set; }

        [SetUp]
        public void SetUp()
        {
            TxScope = new TransactionScope();
        }

        [TearDown]
        public void TearDown()
        {
            if (TxScope != null)
            {
                TxScope.Dispose();
                TxScope = null;
            }
        }
    }
}

Easy as pie.

1 голос
/ 26 июня 2010

Есть целый набор ответов на это. Первое, что нужно сделать, это четко сформулировать, что вы тестируете. Является ли это фасадом API, за которым стоит база данных, объекты DAO, структура вашей базы данных?

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

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

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

0 голосов
/ 02 июля 2010

Что вы тестируете на самом деле, что заставляет вас чувствовать, что это сложно?

Если вы отделите логику своего бизнеса и уровня обслуживания от своего кода персистентности, вы легко сможете изолировать код, который вы хотите объединитьТестирование без необходимости в БД.

Один из важнейших принципов модульного тестирования - это разделение и тестирование в изоляции.Когда у вас есть четкое понимание того, как это сделать, модульное тестирование легко.Когда вы этого не сделаете, юнит-тестирование становится трудным.

...