2009-12-01 6 views
23

NHibernate, ASP.NET MVC 2.0 및 StructureMap을 사용하여 새 프로젝트를 시작하고 테스트를 위해 NUnit 및 Moq을 사용하고 있습니다. 각 컨트롤러에 대해 하나의 공용 생성자를 사용하여 Session을 주입합니다. 응용 프로그램 자체는 잘 작동하지만 유닛 테스트 측면에서 컨트롤러를 테스트하기 위해서는 본질적으로 Session을 조롱해야합니다.Moq를 사용하여 NHibernate Session을 조롱

나는 MOQ로 ISession을 모의 할 때 나는 다음과 같은 오류 메시지가 얻을 : 중간 호출

내 문제의 목록을 기대하는 것 같습니다에

만 속성 액세스가 지원됩니다 을 프레임 워크 CreateQuery 메서드에서 사용자가 있지만 지금은 명확한 문제를 인터넷 검색 후.

나는 두 가지 질문이 있습니다 성공적으로 내 목록을 반환 할 수 있도록 코드를 수정하는 방법을

1)이이 ISession

2)의 의존성 주입을 조롱하는 잘못된 방법입니다 있나요

  [Test] 
      public void DummyTest() 
      { 

       var mock = new Mock<ISession>(); 
       var loc = new Mock<User>(); 
       loc.SetupGet(x => x.ID).Returns(2); 
       loc.SetupGet(x => x.FirstName).Returns("John"); 
       loc.SetupGet(x => x.LastName).Returns("Peterson"); 

       var lst = new List<User> {loc.Object}; 
       mock.Setup(framework => framework.CreateQuery("from User").List<User>()).Returns(lst); 

       var controller = new UsersController(mock.Object); 
       var result = controller.Index() as ViewResult; 
       Assert.IsNotNull(result.ViewData); 
      } 

내가 그냥 (개인 사용자를 조롱하고 목록에 추가가 아닌) 사용자의 하드 코딩 된 목록을 만들 수있는 확신,주의하지만 난 그것을 가지고 내가 코드를 떠날 거라고 생각하세요 지금.

또한이 특정 컨트롤러의 인덱스 동작은 위에서 흉내 낸 CreateQuery 호출을 실행하여 데이터베이스의 모든 사용자를 반환합니다. 이것은 인위적인 예입니다. 세부 정보를 읽지 마십시오. 당신의 도움이

편집에 미리

감사 : 아래의 댓글에 답글 달기에서, 나는 오류의 스택 트레이스를 추가하고있다. 또한 User 클래스의 모든 속성은 가상입니다.

TestCase에 'Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView' 실패 : System.NotSupportedException : 만 속성 액세스가 설정에 중간 호출에 을 지원합니다. 지원되지 않는 표현식 framework.CreateQuery ("사용자"). Moq.ExpressionVisitor.Visit에서 Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall에서 Moq.ExpressionVisitor.Visit (식 EXP)에서 Moq.Mock.AutoMockPropertiesVisitor.VisitMethodCall (MethodCallExpression m) (m MethodCallExpression )에서 (식 Moq.Mock에서 Moq.Mock.GetInterceptor (LambdaExpression 람다, 모의 모의)에서 Moq.Mock.AutoMockPropertiesVisitor.SetupMocks (식 식)에 EXP). Moq.Mock.Setup [T1, TResult]에서 <> c__DisplayClass12 2.<Setup>b__11() at Moq.PexProtector.Invoke[T](Func 1 함수) (모의 모의, 식 1 expression) at Moq.Mock 1.Setup [TResult (Expression`1 식) 컨트롤러 \ UserControllerTest.CS (29,0) : Beta.Tests.Unit.Controllers.UserControllerTest.Details_InValidIndex_ReturnsNotFoundView()

+0

오류 스택 추적을 표시 할 수 있습니까? 사용자 속성은 추상 또는 가상입니까? –

답변

20

다음은 내가 완벽하게 작동하는 것으로 생각한 해결책입니다. 다시, 나는 NHibernate를 테스트하지 않고 있으며 데이터베이스를 테스트하지 않을 것이다. NHibernate에 의존하는 컨트롤러를 테스트하기를 원할 뿐이다. 초기 솔루션의 문제점은 내가 Method를 호출 할뿐만 아니라 MOQ 설정 호출에서 세션의 List 멤버를 읽는 것입니다. 솔루션을 QueryMock과 Session Mock으로 분해하여 이러한 호출을 중단했습니다 (create query는 IQuery 객체를 반환 함). 트랜잭션 모의은

 [Test] 
     public void DummyTest() 
     { 
      var userList = new List<User>() { new User() { ID = 2, FirstName = "John", LastName = "Peterson" } }; 
      var sessionMock = new Mock<ISession>(); 
      var queryMock = new Mock<IQuery>(); 
      var transactionMock = new Mock<ITransaction>(); 

      sessionMock.SetupGet(x => x.Transaction).Returns(transactionMock.Object); 
      sessionMock.Setup(session => session.CreateQuery("from User")).Returns(queryMock.Object); 
      queryMock.Setup(x => x.List<User>()).Returns(userList); 

      var controller = new UsersController(sessionMock.Object); 
      var result = controller.Index() as ViewResult; 
      Assert.IsNotNull(result.ViewData); 
     } 
18

에서 오히려 Session을 조롱하는 것보다, 하나는 단위 테스트를 위해 다른 Configuration을 설정하는 것이 좋습니다. 이 단위 테스트 Configuration은 SQLite 또는 Firebird와 같은 빠른 in-process 데이터베이스를 사용합니다. Fixture 설정에서 처음부터 새로운 테스트 데이터베이스를 생성하고, 스크립트를 실행하여 테이블을 설정하고 초기 레코드 세트를 생성합니다. 테스트 당 설정에서 트랜잭션을 열고 사후 테스트 티 아웃에서 트랜잭션을 롤백하여 데이터베이스를 이전 상태로 복원합니다. 어떤 의미에서는 Session을 조롱하지는 않습니다. 까다로워지기 때문에 실제 데이터베이스를 조롱하고 있기 때문입니다.

+0

감사합니다. 나는 확실히 그것에 대해 생각해 봤고, 내가이 일을 할 수 없다면, 내가가는 길일 것입니다. 하지만이 테스트 프로젝트에서 데이터베이스를 완전히 피하려고합니다. 내가 NHibernate를 조롱 할 수 있다면, 나는 내 테스트를 훨씬 더 잘 제어 할 수 있다고 생각한다.하지만 제안에 감사한다. –

+3

불행히도, NHibernate'Session'은 관련된 객체, 지연된 로딩, 캐싱, 그리고 NHibernate가하는 다른 모든 것들에 관해서는 매우 복잡합니다. 그래서 나는 그것을 조롱하려고 시도하지 않고 데이터베이스를 조롱하려고 노력할 것입니다. NHibernate가 당신의 매핑으로부터 주어진 데이터베이스 시스템을위한 스키마 생성 스크립트를 생성하고, 그 스크립트를 실행하여 fixture-setup에서 스키마를 가진 빈 데이터베이스를 생성하는 것은 쉽습니다. NHibernate에 대한 내 자신의 경험과 Rails와 같은 프레임 워크를 관찰 한 결과, 이것이 근본적으로 유일한 방법이다. – yfeldblum

+0

흠, 네 말이 맞아 ... 너무 좋을거야. 조롱당한 DB를 사용할 필요가 없다. 우리 관계형 모델을 객체 모델로 변환하는 nhibernate가 이미 있다면, 테스트 된 것은 이상하다. 이런 식으로 우리는 직접 테스트 할 수 있어야합니다 ... 좋은 질문과 답변, 건배 :) – Marko

관련 문제