잊지 않겠습니다.

Controller 객체를 사용해서 각 method를 테스트하는 방법은 매우 뛰어난 테스팅 방법이지만, 불행하게도 Session 및 Identify에 대한 내용을 같이 테스팅 하는 것은 불가능하다. 특히, Session에 Wizard Data 또는 사용자에 따른 개인 정보를 저장하고 있는 경우에는 Controller 객체만을 사용하는 것은 불가능하다.

그래서, Mock을 이용해서 HttpContext를 구성하고, 구성된 HttpContext를 ControllerContext로 구성하여 Controller를 사용하게 되면 위와 같은 문제를 모두 해결 할 수 있다.


01.public class FakeSession : HttpSessionStateBase
02.{
03.    private readonly SessionStateItemCollection _sessionItems;
04.    public FakeSession(SessionStateItemCollection sessionItems)
05.    {
06.        _sessionItems = sessionItems;
07.    }
08. 
09.    public override void Add(string name, object value)
10.    {
11.        _sessionItems[name] = value;
12.    }
13. 
14.    public override int Count
15.    {
16.        get
17.        {
18.            return _sessionItems.Count;
19.        }
20.    }
21. 
22.    public override IEnumerator GetEnumerator()
23.    {
24.        return _sessionItems.GetEnumerator();
25.    }
26. 
27.    public override NameObjectCollectionBase.KeysCollection Keys
28.    {
29.        get
30.        {
31.            return _sessionItems.Keys;
32.        }
33.    }
34. 
35.    public override object this[string name]
36.    {
37.        get
38.        {
39.            return _sessionItems[name];
40.        }
41.        set
42.        {
43.            _sessionItems[name] = value;
44.        }
45.    }
46. 
47.    public override object this[int index]
48.    {
49.        get
50.        {
51.            return _sessionItems[index];
52.        }
53.        set
54.        {
55.            _sessionItems[index] = value;
56.        }
57.    }
58.    public override void Remove(string name)
59.    {
60.        _sessionItems.Remove(name);
61.        }
62.}
63. 
64.protected T GetContextedController<t>(T controller, string userName, FakeSession sessionState) where T : ControllerBase
65.{
66.    //Register Route
67.    RouteCollection routes = new RouteCollection();
68.    MvcApplication.RegisterRoutes(routes);
69. 
70.    //Build Mock HttpContext, Request, Response
71.    var mockHttpContext = new Moq.Mock<httpcontextbase>();
72.    var mockRequest = new Moq.Mock<httprequestbase>();
73.    var mockResponse = new Moq.Mock<httpresponsebase>();
74. 
75.    //Setup Mock HttpContext
76.    mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
77.    mockHttpContext.Setup(x => x.Response).Returns(mockResponse.Object);
78.    mockHttpContext.Setup(x => x.Session).Returns(sessionState);
79. 
80.    if(string.IsNullOrEmpty(userName))
81.    {
82.        mockHttpContext.Setup(x => x.User.Identity.IsAuthenticated).Returns(false);
83.        mockRequest.Setup(x => x.IsAuthenticated).Returns(false);
84.    }
85.    else
86.    {
87.        mockHttpContext.Setup(x => x.User.Identity.Name).Returns(userName);
88.        mockHttpContext.Setup(x => x.User.Identity.IsAuthenticated).Returns(true);
89.        mockRequest.Setup(x => x.IsAuthenticated).Returns(true);
90.    }
91.    mockRequest.Setup(x => x.ApplicationPath).Returns("/");
92. 
93.    // Build Request Context
94.    var ctx = new RequestContext(mockHttpContext.Object, new RouteData());
95.    controller.ControllerContext = new ControllerContext(ctx, controller);
96.    return controller;
97.}
98.</httpresponsebase></httprequestbase></httpcontextbase></t>


사용 방법은 다음과 같다.
01.[Test]
02.public void Start()
03.{
04.    _controller = new VirtualMachineController();
05.    SessionStateItemCollection sessionItemCollections = new SessionStateItemCollection();
06.    sessionItemCollections[SessionConstants.Account] = _account;
07.    sessionItemCollections[SessionConstants.ZoneList] = tempZoneList;
08. 
09.    _session = new FakeSession(sessionItemCollections);
10.    _controller = GetContextedController(_controller, LocalConf.AccountName, _session);
11.    _controller.Start("tempVmName");
12.}
Posted by Y2K
,