2009-08-04 2 views
2

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

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

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

ВОПРОС:

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

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

[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

ответ

3

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

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