Модульное тестирование SQLite NHibernate генерирует каскадные отношения - PullRequest
2 голосов
/ 04 августа 2009

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

В этой превосходной статье (http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx) автор утверждает, что "при использовании NHibernate мы обычно хотим протестировать только три вещи:
1) что свойства сохраняются,
2) этот каскад работает как положено 3) что запросы возвращают правильный результат. -) что отображение завершено и правильно (подразумевается)

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

ВОПРОС:

Как вы используете SQLite для тестирования каскадных отношений, особенно если учесть, что он не проверяет ограничения внешнего ключа. Как вы тестируете свою модель, чтобы убедиться, что ограничения внешнего ключа не будут проблемой БД.

Вот некоторые юнит-тесты, которые я придумал для проверки каскадного поведения. Модель - это просто отдел, который может иметь от нуля до нескольких штатных сотрудников с каскадом, установленным на НЕТ.

    [Test]
    public void CascadeSaveIsNone_NewDepartmentWithFetchedStaff_CanSaveDepartment()
    {
        _newDept.AddStaff(_fetchedStaff);
        Assert.That(_newDept.IsTransient(), Is.True);

        _reposDept.SaveOrUpdate(_newDept);
        _reposDept.DbContext.CommitChanges();

        Assert.That(_newDept.IsTransient(), Is.False);
    }

    [Test]
    public void CascadeSaveIsNone_NewDepartmentWithFetchedStaff_CannotSaveNewStaff()
    {
        _newDept.AddStaff(_newStaff);
        Assert.That(_newDept.IsTransient(), Is.True);
        Assert.That(_newStaff.IsTransient(), Is.True);

        _reposDept.SaveOrUpdate(_newDept);
        _reposDept.DbContext.CommitChanges();

        Assert.That(_newDept.IsTransient(), Is.False);
        Assert.That(_newStaff.IsTransient(), Is.True);
    }

    [Test]
    public void CascadeDeleteIsNone_FetchedDepartmentWithFetchedStaff_Error()
    {
        _fetchedDept.AddStaff(_fetchedStaff);
        _reposDept.SaveOrUpdate(_fetchedDept);
        _reposStaff.DbContext.CommitChanges();

        _reposDept.Delete(_fetchedDept);
        var ex = Assert.Throws<GenericADOException>(() => _reposDept.DbContext.CommitChanges());

        Console.WriteLine(ex.Message);
        Assert.That(ex.Message, Text.Contains("could not delete:"));
        Console.WriteLine(ex.InnerException.Message);
        Assert.That(ex.InnerException.Message, Text.Contains("The DELETE statement conflicted with the REFERENCE constraint"));
    }

    [Test]
    public void Nullable_NewDepartmentWithNoStaff_CanSaveDepartment()
    {
        Assert.That(_newDept.Staff.Count(), Is.EqualTo(0));

        var fetched = _reposDept.SaveOrUpdate(_newDept);
        Assert.That(fetched.IsTransient(), Is.EqualTo(false));
        Assert.That(fetched.Staff.Count(), Is.EqualTo(0));
    }

Третий тест, ".._ FetchedDepartmentWithFetchedStaff_Error", работает с Sql Server, но не с SQLite, поскольку последний не проверяет ограничения внешнего ключа.

Вот тесты для другой стороны отношений; StaffMember может иметь один отдел с каскадом NONE.

    [Test]
    public void CascadeSaveIsNone_NewStaffWithFetchedDepartment_CanSaveStaff()
    {
        _newStaff.Department = _fetchedDept;
        _reposStaff.SaveOrUpdate(_newStaff);
        _reposStaff.DbContext.CommitChanges();

        Assert.That(_newStaff.Id, Is.GreaterThan(0));
    }

    [Test]
    public void CascadeSaveIsNone_NewStaffWithNewDepartment_Error()
    {
        _newStaff.Department = _newDept;
        Assert.That(_newStaff.IsTransient(), Is.True);

        var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff));
        Console.WriteLine(ex.Message);
        Assert.That(ex.Message, Text.Contains("not-null property references a null or transient value"));
    }

    [Test]
    public void CascadeDeleteIsNone_FetchedStaffWithFetchedDepartment_DeletesTheStaff_DoesNotDeleteTheDepartment()
    {
        _newStaff.Department = _fetchedDept;
        _reposStaff.SaveOrUpdate(_newStaff);
        _reposStaff.DbContext.CommitChanges();

        _reposStaff.Delete(_newStaff);
        Assert.That(_reposStaff.Get(_newStaff.Id), Is.Null);
        Assert.That(_reposDept.Get(_fetchedDept.Id), Is.EqualTo(_fetchedDept));
    }

    [Test]
    public void NotNullable_NewStaffWithUnknownDepartment_Error()
    {
        var noDept = new Department("no department");
        _newStaff.Department = noDept;

        var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff));
        Console.WriteLine(ex.Message);
        Assert.That(ex.Message, Text.Contains("not-null property references a null or transient"));
    }

    [Test]
    public void NotNullable_NewStaffWithNullDepartment_Error()
    {
        var noDept = new Department("no department");
        _newStaff.Department = noDept;

        var ex = Assert.Throws<PropertyValueException>(() => _reposStaff.SaveOrUpdate(_newStaff));
        Console.WriteLine(ex.Message);
        Assert.That(ex.Message, Text.Contains("not-null property references a null or transient"));
    }

Эти тесты прошли успешно на Sql Server и SQLite. Могу ли я доверять тестам SQLite? Это стоящие тесты?

Приветствия
Berryl

1 Ответ

3 голосов
/ 04 августа 2009

Насколько я понимаю, статья посвящена тестированию картографирования NHibernate. По моему мнению, это не имеет ничего общего с проблемами, связанными с БД, но с тестированием атрибутов nhibernate, которые вы установили в своем отображении. Нет необходимости утверждать, что невозможно создать неверные данные: вам нужно только доказать, что ваш код создает желаемый результат и / или проверяет то, что вы хотите проверить. Вы можете проверить каскад, каскад-удаление и удаление-сирота. все, что вы хотите, как вы делаете это в тестах, работающих с sqlite. Но третий тест пытается проверить ограничение, о котором ничего не беспокоит.

Если вы хотите проверить свои ограничения Db, вам действительно следует использовать ваш производственный db, а не sqlite. Вы можете сделать это с или без спящего режима, но это не имеет ничего общего с вашим отображением. С другой стороны, если вам действительно нужен обходной путь для ваших тестов внешнего ключа с SQLite, вы можете попробовать использовать foreign_key_trigger_generator . Я не пробовал, но, кажется, генерирует триггеры before-insert-Триггеры, которые гарантируют существование указанного Pk. Может быть, вы могли бы написать комментарий, если этот инструмент полезен.

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