2017-11-24 25 views
0

새로운 기술을 배우기위한 간단한 응용 프로그램을 작성 중입니다. 나는 내 응용 프로그램을 작성하는 단위 테스트에 붙어있어 :NHibernate를 사용하여 엔티티를 삭제할 때 "not-null 속성이 null 값이나 일시적인 값을 참조합니다"

[Test] 
    public void LessonChangeSubjectShouldNotAffectFormerSubjectPersistence() 
    { 
     // given 
     Lesson ExampleLesson = TestDataFactory.CreateLesson(); 
     Save(ExampleLesson); 
     Refresh(ref ExampleLesson); 
     Subject formerSubject = ExampleLesson.Subject; 

     // when 
     Subject subject = TestDataFactory.CreateSubject(); 
     _subjectService.Save(subject); 
     ExampleLesson.ChangeSubject(subject); 
     Update(ExampleLesson); 
     _subjectService.Update(formerSubject); 
     Refresh(ref ExampleLesson); 
     formerSubject = _subjectService.Get(formerSubject.Id); 
     subject = _subjectService.Get(subject.Id); 

     // then 
     ExampleLesson.Subject.Should().Be(subject); 
     formerSubject.Should().NotBeNull(); 
     formerSubject.Lessons.Should().NotContain(ExampleLesson); 

     Refresh(ref ExampleLesson); 

     _subjectService.Delete(formerSubject); 
     Refresh(ref ExampleLesson); 
     Delete(ExampleLesson); 
    } 

이 시나리오는 다음과 같습니다 기본 임의의 주제와 교훈 저장 만들기

  1. 그것을
  2. 새로운 새로운 제목과 변화 수업 주제를 작성 하나
  3. 확인이

이 시나리오가 성공 된 피사체가 여전히 존재하는지 여부를하지만 어디 갔지 - null이 아닌 프로퍼티 참조 null 또는 과도 값 Register.Core.Model.Lesson.Subject

제목 : N은 테스트를 청소에 관해서는 오류

NHibernate.PropertyValueException와 마지막 줄에 실패 다음과 같이 레슨 클래스의 필드 매핑됩니다 :

References(x => x.Subject) 
.Cascade.SaveUpdate() 
.Column("SubjectId") 
.Fetch.Select() 
.ForeignKey("FK_Lessons_Subjects") 
.Index("IX_Subject") 
.LazyLoad() 
.Not.Nullable(); 

그리고 수업은 주제 클래스의 컬렉션으로 매핑됩니다 :

HasMany(x => x.Lessons) 
.Access.CamelCaseField(Prefix.Underscore) 
.Cascade.All() 
.Fetch.Select() 
.ForeignKeyConstraintName("FK_Lessons_Subjects") 
.Inverse() 
.KeyColumn("SubjectId") 
.Not.KeyNullable() 
.LazyLoad(); 

나는

Refresh(ref ExampleLesson); 
    Delete(ExampleLesson); 

가 NHibernate에 아무런 불만이 없습니다 및 테스트를 통과하여

_subjectService.Delete(formerSubject); 

를 교환합니다. 나는 무슨 일이 일어나고 왜 주문이 중요한지 궁금하다. 누군가가 내 문제에 대한 해결책을 제시 할 수 있다면 또한 매우 감사 할 것입니다. 미리 감사드립니다.

+0

@ RadimKöhler 지금 formerSubject'는 우리가 전에 새로운 부모를 얻을 수 RadimKöhler @ 다른 –

+0

에 따라 변화하기 때문에 테스트에 수업 주제를 변경하기 때문에 잘못된 행동이, 인도 ExampleLesson 삭제 '삭제 새로운 것을 저장하고 저장합니다. 수업은 이전 부모가 삭제되기 전에 새로운 부모를 얻습니다. –

답변

0

오류는 별칭 문제로 인한 것일 수 있습니다. 거기에 수업의 사본이 두 개 있으며, 수업 컬렉션이 새로 고침의 영향을받지 않았기 때문에 formersubject가 액세스 할 수 있습니다.

내 조언

그것을 모델링하기 :

피사체가 수업 당신은 불필요하게 유효한 모델을 유지하기 위해 그것을 사용하지 않고 모든 시간을 새로 고쳐야 할

의 컬렉션을 필요는 없습니다. 시간이 지남에 따라 커져서 모든 종류의 문제를 일으킬 것입니다. 데이터베이스 호출 대신 메모리 조작이 될 필터/열거/정렬이 필요합니다.

do not abstract away the ORM

실제 비즈니스 로직에 대한 서비스를합니다. NHibernate의 Session이 이미 하나이기 때문에 DataAccessObjects (DAO)는 중복됩니다. unittests에 대한 Sqlite 메모리 데이터베이스는 쿼리를 테스트하여 올바른 결과를 반환하는 이점이 있습니다.

예제 코드

class Lesson : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual Subject Subject { get; set; } 

    public void ChangeSubject(Subject subject) 
    { 
     // do some checks 

     Subject = subject; 
    } 
} 

class Subject : Entity 
{ 
    public string Name { get; set; } 
} 


[Test] 
public void LessonChangeSubjectShouldNotAffectFormerSubjectPersistence() 
{ 
    var session = GetInMemorySession(); 
    // given 
    Lesson exampleLesson = new Lesson { Name = "Lesson1", Subject = new Subject { Name = "Subject1" } }; 
    session.Save(exampleLesson.Subject); // because we havent set cascade.save 
    session.Save(exampleLesson); 
    var formerSubjectId = exampleLesson.Subject.Id; 

    // when 
    Subject subject = new Subject { Name = "Subject2" }; 
    session.Save(subject); 
    exampleLesson.ChangeSubject(subject); 
    session.Flush(); // save all changes 
    session.Clear(); 

    var formerSubject = session.Get<Subject>(formerSubjectId); 
    subject = session.Get<Subject>(subject.Id); 

    // then 
    exampleLesson.Subject.Should().Be(subject); 
    formerSubject.Should().NotBeNull(); 

    // technically not needed because the inmemory database is gone after this test 
    session.Delete(formerSubject); 
    session.Delete(subject); 
}