2009-04-01 28 views
7

Tôi mới vào Mocking frameworks và đã bắt đầu sử dụng RhinoMocks để hỗ trợ với MVC App Unit Testing của tôi.Làm thế nào để sử dụng Rhino Mocks để Mock một HttpContext.Application

Tôi đang sử dụng Scott Hanselmanns MVC Mock Helper để trợ giúp chế nhạo HttpContext. Tôi đã thành công (sau một thời gian) đã chế nhạo một số thứ tôi cần nhưng đã trở nên bất ngờ khi nói đến thuộc tính Ứng dụng của HttpContext.

Trong ứng dụng của tôi, tôi lưu giữ một đối tượng trong ứng dụng và lấy nó trong vòng một điều khiển như:

SomeObj foo = (SomeObj)Application["fooKey"]; 

này được tạo ra trên Application_Start trong MVC App của tôi.

cập nhật sau ĐÁP FIRST (thêm mã cho rõ ràng) Hiện nay trong các thiết lập thử nghiệm tôi làm:

HttpContextBase mockHttpBase = mocks.FakeHttpContext(); 
controllerToTest = new SomeController(); 
mocks.SetFakeControllerContext(controllerToTest); 


HttpApplicationStateBase appState = 
    MockRepository.GenerateStub<HttpApplicationStateBase>(); 

Globals tmpAppGlobals = 
    new Globals(); 

mockHttpBase.Expect(ctx => ctx.Application).Return(appState); 
mockHttpBase.Expect(ctx => ctx.Application[Globals.GlobalsKey]). 
    Return(tmpAppGlobals); 

Trong thiết lập thử nghiệm đơn vị của tôi, tôi làm:

Globals tmpAppGlobals = new Globals(); 
controllerToTest.ControllerContext.HttpContext. 
      Expect(ctx => ctx.Application[Globals.GlobalsKey]). 
Return(tmpAppGlobals); 

Cuộc gọi này ném một ngoại lệ NullReference, cho đối tượng Application.

Câu hỏi của tôi là hai lần:

1) Đây có phải là cách tiếp cận đúng hay tôi đã làm điều gì đó sai từ góc độ thiết kế/kiến ​​trúc?

2) Tại sao tính năng này không hoạt động ?!

Xin cảm ơn trước.

+1

Tôi đã chỉnh sửa câu trả lời của mình; kiểm tra xem nó có hoạt động không? – Randolpho

Trả lời

1

Nếu không xóa quá sâu, điều này có vẻ chính xác.

Thuộc tính Ứng dụng là ảo trên HttpContextBase, vì vậy bạn có thể thiết lập giá trị trả về cho nó từ Tê giác - Giả sử bạn đang chế nhạo HttpContextBase như bài đăng của Scott Hanselmanns.

Một số nguyên nhân có thể, được thực sự chỉ là đoán từ thiếu thông tin:

  • Bạn có thiết lập trở lại cho controllerToTest.ControllerContext?
  • Bạn đã thiết lập trả lại cho rằng đối tượng HttpContext property?
  • Bạn đã thiết lập trả lại cho rằng đối tượng Thuộc tính ứng dụng?

Lý do tôi hỏi thường là khi bạn thiết lập kỳ vọng, bạn đã tham chiếu đến đối tượng sẽ được gọi là một phần của bài kiểm tra của bạn, vì vậy bạn sẽ không thực hiện chuỗi thuộc tính giống như controllerToTest.ControllerContext.HttpContext. Expect() cuộc gọi.

Edit:

Tôi nghĩ rằng tôi nhìn thấy được vấn đề, và tôi nghĩ rằng đó là với phần này:

Expect(ctx => ctx.Application[Globals.GlobalsKey])

Tôi nghĩ rằng bạn đang giả định rằng indexers làm việc giống như tài sản, khi họ không. Những gì bạn thực sự cần phải làm là thiết lập một kỳ vọng vào đối tượng appState của bạn để nhận một cuộc gọi đến mục tài sản, như thế này:

// setup expectations -- assumes some of the expectations and mocks 
// the from original question 
mockHttpBase.Expect(ctx => ctx.Application).Return(appState); 
appState.Expect(ctx => ctx.Item(Globals.GlobalsKey)).Return(tmpAppGlobals); 

// run the test 
+1

Randolpho, cảm ơn. Tôi đã thiết lập các trả về cho bối cảnh điều khiển, httpContext và ứng dụng [Tôi nghĩ]. Tôi đã thêm một số mã bổ sung để làm rõ. – Lewis

+0

Ồ, tôi hiểu; Tôi đã không đọc bài đăng trên blog hoàn toàn đủ. – Randolpho

+0

Cảm ơn một lần nữa Randolpho. Tôi không thể lấy ví dụ của bạn để làm việc, thật không may. Tôi đã quay trở lại để viết các đối tượng Mock của riêng mình cho các đối tượng HttpContext và con và có nhiều thành công hơn khi làm những việc theo cách đó. – Lewis

1

bạn có thể sử dụng dưới đây để biết Moq. Nó đã cho tôi một thời gian làm thế nào để giả lập HttpApplication, và appState.Object là phương thức trả về duh!

public static HttpContextBase FakeHttpContext() 
    { 
     var context = new Mock<HttpContextBase>(); 
     var request = new Mock<HttpRequestBase>(); 
     var response = new Mock<HttpResponseBase>(); 
     var session = new FakeHttpSessionState(); 
     var server = new Mock<HttpServerUtilityBase>(); 
     var appState = new Mock<HttpApplicationStateBase>(); 

     context.Setup(ctx => ctx.Request).Returns(request.Object); 
     context.Setup(ctx => ctx.Response).Returns(response.Object); 
     context.Setup(ctx => ctx.Session).Returns(session); 
     context.Setup(ctx => ctx.Server).Returns(server.Object); 
     context.Setup(ctx => ctx.Application).Returns(appState.Object); 

     //emulate session (HttpContext.Current.Session) 
     var contx = new HttpContext(new MyApp.NUnit.Tests.Fakes.FakeHttpWorkerRequest()); 
     contx.Items["AspSession"] = CreateSession(); 

     HttpContext.Current = contx; 

     return context.Object; 
    } 
+2

Xin lỗi, tôi dày đặc ở đâu là "FakeHttpSessionState" và "CreateSession" được xác định? – CmdrTallen

Các vấn đề liên quan