2010-02-05 3 views
0

MSpec을 처음 사용하고 ASP.NET MVC 테스트를 작성한 방법이 올바른지 알고 싶습니다. 테스트는 통과하지만 필자가 작성한 방식이 맘에 들지 않으며 어색하게 보입니다. 나는 확실히 뭔가를 놓친다. 사전에MSpec을 사용한 ASP.NET MVC 테스트. 이것이 맞습니까, 아니면 리팩토링이 필요합니까?

public class AccountControllerTests3 
{ 
    protected static AccountController controller; 
    static IFormsAuthenticationService formsService; 
    static IMembershipService membershipService; 
    protected static ActionResult result; 
    protected static LogOnModel model; 

    Establish context =() => 
    { 
     var controllerBuilder = new TestControllerBuilder(); 

     formsService = MockRepository.GenerateStub<IFormsAuthenticationService>(); 
     membershipService = MockRepository.GenerateStub<IMembershipService>(); 
     model = MockRepository.GenerateStub<LogOnModel>(); 

     controller = 
      controllerBuilder.CreateController<AccountController>(new object[] 
                    { 
                     formsService, 
                     membershipService 
                    }); 
    }; 

    Because user_logs =() => 
    { 
     bool rememberMe = false; 

     membershipService.Stub(
      x => x.ValidateUser("bdd", "mspec")).Return(true); 
     formsService.Stub(x => x.SignIn("bdd", rememberMe)); 

     controller.ModelState.IsValid.ShouldBeTrue(); 
    }; 
} 

[Subject(typeof(AccountController), "LogInTests")] 
public class When_logging_into_application_with_good_login_and_password : AccountControllerTests3 
{ 
    private It user_should_be_redirected_to_the_home_page =() => 
                   { 
                    model.UserName = "bdd"; 
                    model.Password = "mspec"; 

                    result = controller.LogOn(model, string.Empty); 

                    result.AssertActionRedirect().ToAction<HomeController>(
                     x => x.Index()); 
                   }; 
} 

[Subject(typeof(AccountController), "LogInTests")] 
public class When_logging_into_application_with_bad_login_and_password : AccountControllerTests3 
{ 
    It The_error_message_should_be_shown =() => 
              { 
               model.UserName = "BAD"; 
               model.Password = "BAD"; 

               result = controller.LogOn(model, string.Empty); 

               controller.ModelState[""].Errors[0].ErrorMessage.ShouldEqual(
                "The user name or password provided is incorrect."); 
              }; 
} 

감사합니다,

토마스

답변

4

내 목표 중 하나는 MSpec으로 테스트를 작성할 때 "Assert"또는 "It"을 한 줄로 가져 오는 것입니다. MSpec은 컨텍스트 (현재 클래스 및 모든 기본 클래스와 Because 절에서 Establish 절로 구성됨) 만 실행하고 모든 Specification (It 절)이 뒤 따르는 점에서 NUnit과 다릅니다.

이것은 It 절에서 어떠한 행동도하지 않고 강제적으로 관찰하도록 명시 적으로 설계되었습니다.

여기서 실제로하는 일은 NUnit과 같은 MSpec을 사용하는 것입니다. 단일 클래스에서 테스트를 다시 작성하고 재 작성하십시오 (상속 없음 사용). 거꾸로 ... It에서, 당신이 단언하고자하는 것을 주장하는 한 줄을 배치하십시오. 아마 AssertRedirect. 왜냐하면, 이라는 하나의 라인을 넣으려고하면 관찰 결과를 관찰 할 수 있기 때문입니다. 이것은 아마 컨트롤러의 로그온 방법에 대한 호출 일 것입니다. 마지막으로, "컨텍스트 설정"에서 다른 모든 것을 넣고 싶습니다.

잠시 후 컨텍스트 설정 만 기본 클래스로 가져올 수 있지만 전체 하위 클래스가 이해의 측면에서 독창적 인 지 확인하십시오. 독자는 실제 스펙이 무엇을하는지 이해하기 위해 기본 클래스를 읽을 필요가 없습니다. 의식 구현 세부 사항을 숨기고 있지만 설명적인 메소드 이름 뒤에 숨기도록하십시오.

나는 확실하지 않다 다른 라인있다 :

controller.ModelState.IsValid.ShouldBeTrue();

테스트의 경우 테스트는 자체 It 절에 있어야합니다. 정말로, 이것을 테스트하고 싶습니까? 너 여기서 뭘 시험해? 모델이 유효한지 여부에 따라 컨트롤러가 조치를 취해야합니까? 해당 작업의 결과를 관찰 할 수 없어야합니다 (로그인 오류 대신 유효성 검사 오류). 당신이 정말로 을 시험 할 필요가 있는지 궁금합니다..

먼저 R #으로 스타일을 지정하기 위해 체크 아웃해야 할 몇 가지 사항이 있습니다. 테스트가 R #의 기본값으로 떨어지는 것 같습니다.여기이 싸움을하는 방법에 대해 게시 :

http://codebetter.com/blogs/aaron.jensen/archive/2008/10/19/getting-resharper-and-vs-to-play-nice-with-mspec.aspx 또한

가, 제임스 브룸 몇 가지 체크 아웃 가치가 좋은 MVC MSpec 확장이 있습니다

http://jamesbroo.me/introducing-machinespecificationsmvc/

행운을 빌어 요하고 즐기십시오! 다른 관련이없는 질문이 있으면 Twitter에서 저를 핑 소리내어보십시오.

+0

답장을 보내 주셔서 감사합니다. 저는 회선 컨트롤러를 제거 할 수 있다는 것에 동의합니다 .ModelState.IsValid.ShouldBeTrue(); 기본 클래스를 피하는 것이 좋습니다. 그래서 내가 두어야 할 곳은 두 개의 클래스로 나뉘어져 있니? 감사합니다. –

+0

기본 클래스가 없으면 서로 다른 두 가지 컨텍스트가 있습니다. 그래서 예, 두 가지 다른 종결 조항과 서로 다른 두 개의 확립 컨텍스트 조항이 있습니다. –

+0

좋아요, 그렇다면 위임 설정에서했던 일반적인 구성 코드를 어디에 정의해야합니까? –

1

여기 발언이다 : 대신 CreateController 방법을 사용 InitializeController를 사용하는 것이 컴파일 시간 안전하고 우호적 리팩토링 때문이다.

대신 :

controller = controllerBuilder.CreateController<AccountController>(
    new object[] { formsService, membershipService }); 

해야 할 것 : 당신이 컨트롤러 생성자 인자를 변경하고 런타임에 날려 버리겠다 경우 두 번째는 컴파일 -을 생성하면서 첫 번째는 여전히 컴파일

controller = new AccountController(formsService, membershipService); 
controllerBuilder.InitializeController(controller); 

시간 오류.

+0

감사합니다. 나머지 검사는. 그것은 MSpec의 관점에서 올바른가요? –

관련 문제