2008-10-06 3 views
44

여기에 대한 답변은 읽기와 컨트롤러 및 조롱을 테스트하지만 세션 값 (또는 다른 컨텍스트 기반 변수를 읽고 설정하는 ASP.NET MVC 컨트롤러를 테스트하는 방법을 아직 이해할 수 없습니다. .) 테스트 메소드에 (세션) 컨텍스트를 어떻게 제공합니까? 답변을 조롱하고 있습니까? 누구든지 예제가 있습니까? 기본적으로 컨트롤러 메서드를 호출하고 컨트롤러에서 해당 세션을 사용하기 전에 세션을 위조하고 싶습니다. 어떤 아이디어?ASP/NET MVC : 세션이있는 컨트롤러를 테스트 하시겠습니까? 조롱?

답변

43

체크 아웃 스티븐 발터의 게시물 : MVC RC 1 ControllerContext와

ASP.NET MVC Tip #12 – Faking the Controller Context

[TestMethod] 
public void TestSessionState() 
{ 
    // Create controller 
    var controller = new HomeController(); 


    // Create fake Controller Context 
    var sessionItems = new SessionStateItemCollection(); 
    sessionItems["item1"] = "wow!"; 
    controller.ControllerContext = new FakeControllerContext(controller, sessionItems); 
    var result = controller.TestSession() as ViewResult; 


    // Assert 
    Assert.AreEqual("wow!", result.ViewData["item1"]); 

    // Assert 
    Assert.AreEqual("cool!", controller.HttpContext.Session["item2"]); 
} 
+3

나는이 URL을 위해 발굴해야했다. 그래서 여기있다 : http://stephenwalther.com/blog/archive/2008/07/01/asp-net-mvc-tip-12-faking-the-controller-context. aspx – blu

+3

명백하지는 않지만 FakeControllerContext는 사용자 정의 클래스입니다. 여기서 소스를 볼 수 있습니다. http://stephenwalther.com/Downloads/Tips/Tip12/Tip12.zip –

+0

위의 소스 링크가 죽은 것 같습니다. 누구나 복사본을 가지고 있습니까? – Flores

12

ASP.NET MVC 프레임 워크는 인터페이스 대신 추상 기본 클래스를 사용하기 때문에 모의 친화적 인 것이 아니며 테스트하기에 너무 많은 마찰을 일으 킵니다. 우리는 요청 별 및 세션 기반 저장을위한 추상화 작성을했습니다. 우리는 이러한 추상화를 매우 가볍게 유지하고 컨트롤러는 요청 별 또는 세션 별 저장을위한 추상화에 의존합니다.

예를 들어 양식 승인 자료를 관리하는 방법은 다음과 같습니다. 같은 구체적인 구현

public interface ISecurityContext 
{ 
    bool IsAuthenticated { get; } 
    IIdentity CurrentIdentity { get; } 
    IPrincipal CurrentUser { get; set; } 
} 

: 우리는 ISecurityContext이

public class SecurityContext : ISecurityContext 
{ 
    private readonly HttpContext _context; 

    public SecurityContext() 
    { 
     _context = HttpContext.Current; 
    } 

    public bool IsAuthenticated 
    { 
     get { return _context.Request.IsAuthenticated; } 
    } 

    public IIdentity CurrentIdentity 
    { 
     get { return _context.User.Identity; } 
    } 

    public IPrincipal CurrentUser 
    { 
     get { return _context.User; } 
     set { _context.User = value; } 
    } 
} 
2

스콧 Hanselman은이 MVC와 방법에 create a file upload quickapp에 대한 게시물을 가지고 설명 특별히 moking 및 것은 해결 "어떻게 때로 믿을 것을 조롱하는 친절하게 조롱해라. "

+0

Hanselman은을 구출 ... – Codewerks

5

조롱이 상당히 쉬운 것으로 나타났습니다. 다음은 moq를 사용하여 httpContextbase (요청, 세션 및 응답 객체가 포함 된)를 조롱하는 예제입니다.

희망이 있습니다. 컨트롤러 컨텍스트 꾀병에

+2

은 와우, 많은 작업은이 명확하게 "너무 많이 설정되어 하나의 방법을 :) 조롱이다 "냄새가 나는데, 이는 인터페이스가 아닌 기본 기본 클래스를 종속성 솔기로 사용했기 때문입니다. – chadmyers

+1

물론, 설치 코드를 "도우미"클래스에두고 반복해서 사용하는 몇 가지 프로젝트를 보았습니다. – Korbin

+0

참고로, 만약 당신의 테스트가 당신이 '도우미'수업을 필요로하는 많은 셋업을 필요로한다면, 당신은 고통과 마찰을 줄 것입니다. – chadmyers

8

는 HttpContext를 감싸고 속성으로 노출합니다. 이것은 조롱을 훨씬 쉽게 만듭니다. MOQ와 세션 변수를 조롱하기 위해 다음을 수행하십시오

var controller = new HomeController(); 
var context = MockRepository.GenerateStub<ControllerContext>(); 
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue"); 
controller.ControllerContext = context; 

은 자세한 내용은 Scott Gu's post를 참조하십시오.

0

HttpContext가 고정되어 있기 때문에 Typemock Isolator를 사용하여이를 모의합니다. Typemock에는 Ivonna이라고하는 ASP.NET unit testing 용 추가 기능 사용자 지정 기능이 있습니다.

2

다음 솔루션을 사용하여 다른 모든 컨트롤러가 상속 한 컨트롤러를 만들었습니다. 다음과 같이

public class TestableController : Controller 
{ 

    public new HttpSessionStateBase Session 
    { 
     get 
     { 
      if (session == null) 
      { 
       session = base.Session ?? new CustomSession(); 
      } 
      return session; 
     } 
    } 
    private HttpSessionStateBase session; 

    public class CustomSession : HttpSessionStateBase 
    { 

     private readonly Dictionary<string, object> dictionary; 

     public CustomSession() 
     { 
      dictionary = new Dictionary<string, object>(); 
     } 

     public override object this[string name] 
     { 
      get 
      { 
       if (dictionary.ContainsKey(name)) 
       { 
        return dictionary[name]; 
       } else 
       { 
        return null; 
       } 
      } 
      set 
      { 
       if (!dictionary.ContainsKey(name)) 
       { 
        dictionary.Add(name, value); 
       } 
       else 
       { 
        dictionary[name] = value; 
       } 
      } 
     } 

     //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs. 

    } 

} 

그런 다음 코드를 사용 :

public class MyController : TestableController { } 
관련 문제