在一个控制器模拟服务器 [英] Mock server in a Controller
问题描述
我有以下线在我的控制器:
字符串lTempPath = Path.Combine(使用Server.Mappath(〜/温度),lRandomFileName);
问题是服务器是不是虚拟的,只能用一个getter访问。
我收到了
的方法或操作未实现。
块引用>我怎么能嘲笑这台服务器?
我所创建的测试如下:
[TestCase的]
公共无效previewActionShouldGenerateUrlOfPdf()
{
//安排
VAR服务器= MockRepository.GenerateMock<&的HttpServerUtilityBase GT;();
server.Stub(S = GT; s.MapPath(〜temp的))返回(〜/ temp的)。
VAR的HttpContext = MockRepository.GenerateMock< HttpContextBase>();
httpContext.Stub(HC = GT; hc.Server).Return(服务器);
httpContext.Server.Stub(S = GT; s.MapPath(〜/温度))返回(〜/ temp的)。 VAR控制器=新StudiesController()
{
ReportingService = MockRepository.GenerateMock< IReportingService>()
SecurityService = MockRepository.GenerateMock< ISecurityService>()
};
controller.ControllerContext =新的ControllerContext(HttpContext的,新的RouteData(),控制器); controller.ReportingService.Stub(RS => rs.GetStudyByGID(新的GUID()))返回(新研究());
controller.ReportingService.Stub(RS => rs.ListPractices())返回(新[] {新实践(),新实践()});
controller.SecurityService.Stub(SS => ss.GetUser())。IgnoreArguments()返回(新用户()); controller.ControllerContext.HttpContext = MockRepository.GeneratePartialMock&所述; FakeHttpContext&GT(http://test.com);
controller.HttpContext.User =新FakePrincipal(新FakeIdentity(测试),新的字符串[0]);
controller.ControllerContext.HttpContext.Stub(X => x.Request).Return(MockRepository.GenerateMock&下; Htt的prequestBase>());
controller.ControllerContext.HttpContext.Request.Stub(X => x.Url).Return(新的URI(http://test.com)); controller.ReportingService.Stub(
RS =>
rs.GenerateReport(新研究(),新实践(),新用户(),假的,ReportGenerationOutputFormat.PDF))IgnoreArguments()返回(新StudyReportSnapshot()); VAR内容=新ContentResult类型(); //法案 VAR的结果=(ContentResult类型)控制器preVIEW(新的GUID()); //断言
Assert.AreEqual(result.Content,content.Content); }
解决方案假设你正在使用某种IOC / DI容器,你不应该依赖于
Controller.Server
。相反,你应该使用的HttpServerUtilityBase
。这个例子假定Ninject作为IOC容器,但任何流行的容器会做什么:
首先,注册
的HttpServerUtilityBase
与IOC容器像这样:kernel.Bind<&的HttpServerUtilityBase GT;()ToMethod(C =>新建HttpServerUtilityWrapper(HttpContext.Current.Server))。
这将确保在运行时,您的应用程序将使用当前请求的服务器属性。
然后,添加一个构造函数到控制器接受的一个实例
的HttpServerUtilityBase
:公共myController的(服务器的HttpServerUtilityBase)
{
this._server =服务器;
}现在,你在哪里调用之前的任何地方
使用Server.Mappath
,只需拨打_server.MapPath
代替。最后,在你的测试,你可以嘲笑的HttpServerUtilityBase像这样(假设起订量为模拟框架):
VAR服务器=新的模拟<&的HttpServerUtilityBase GT;();
server.Setup(S => s.MapPath(It.IsAny<串>()))返回<串>(S => / *设置你怎么想的MapPath在这里* /行为);修改
既然你提到你不使用DI框架,可以求助于穷人的依赖注入。本质上添加一个重载的构造函数:
公共myController的()
:这(新HttpServerUtilityWrapper(HttpContext.Current.Server))
{
}公共myController的(服务器的HttpServerUtilityBase)
{
this._server =服务器;
}这将使生产code使用当前Web请求,但你可以创建自己的实现
的HttpServerUtilityBase
的使用进行测试。I have the following line in my controller:
string lTempPath = Path.Combine(Server.MapPath("~/Temp"), lRandomFileName);
Problem is Server is not virtual and can only be accessed with a getter.
I get a
"The method or operation is not implemented."
How can I mock this server?
The test I have created is as below:
[TestCase] public void PreviewActionShouldGenerateUrlOfPdf() { //Arrange var server = MockRepository.GenerateMock<HttpServerUtilityBase>(); server.Stub(s => s.MapPath("~Temp")).Return("~/Temp"); var httpContext = MockRepository.GenerateMock<HttpContextBase>(); httpContext.Stub(hc => hc.Server).Return(server); httpContext.Server.Stub(s => s.MapPath("~/Temp")).Return("~/Temp"); var controller = new StudiesController() { ReportingService = MockRepository.GenerateMock<IReportingService>(), SecurityService = MockRepository.GenerateMock<ISecurityService>() }; controller.ControllerContext = new ControllerContext(httpContext, new RouteData(), controller); controller.ReportingService.Stub(rs => rs.GetStudyByGID(new Guid())).Return(new Study()); controller.ReportingService.Stub(rs => rs.ListPractices()).Return(new[] { new Practice(), new Practice() }); controller.SecurityService.Stub(ss => ss.GetUser("")).IgnoreArguments().Return(new User()); controller.ControllerContext.HttpContext = MockRepository.GeneratePartialMock<FakeHttpContext>("http://test.com"); controller.HttpContext.User = new FakePrincipal(new FakeIdentity("test"), new string[0]); controller.ControllerContext.HttpContext.Stub(x => x.Request).Return(MockRepository.GenerateMock<HttpRequestBase>()); controller.ControllerContext.HttpContext.Request.Stub(x => x.Url).Return(new Uri("http://test.com")); controller.ReportingService.Stub( rs => rs.GenerateReport(new Study(), new Practice(), new User(), false, ReportGenerationOutputFormat.PDF)).IgnoreArguments().Return(new StudyReportSnapshot()); var content = new ContentResult(); //Act var result = (ContentResult)controller.Preview(new Guid()); //Assert Assert.AreEqual(result.Content, content.Content); }
解决方案Assuming you're using some sort of IOC/DI container, you shouldn't depend on
Controller.Server
. Instead you should useHttpServerUtilityBase
.This example assumes Ninject as the IOC container, but any of the popular containers will do:
First, register
HttpServerUtilityBase
with your IOC container like so:kernel.Bind<HttpServerUtilityBase>().ToMethod(c => new HttpServerUtilityWrapper(HttpContext.Current.Server));
This will make sure that at run time your app will use the current request's server property.
Then, add a constructor to your controller that accepts an instance of
HttpServerUtilityBase
:public MyController(HttpServerUtilityBase server) { this._server = server; }
Now, anywhere before where you were calling
Server.MapPath
, just call_server.MapPath
instead.Finally, in your tests, you can mock HttpServerUtilityBase like so (assuming Moq as the mocking framework):
var server = new Mock<HttpServerUtilityBase>(); server.Setup(s => s.MapPath(It.IsAny<string>())).Returns<string>(s => /* set up how you want MapPath to behave here */);
EDIT
Since you mentioned you're not using an DI framework, you can resort to "Poor Man's Dependency Injection". Essentially adding an overloaded constructor:
public MyController() : this(new HttpServerUtilityWrapper(HttpContext.Current.Server)) { } public MyController(HttpServerUtilityBase server) { this._server = server; }
This will allow production code to use the current web request, but then you can create your own implementation of
HttpServerUtilityBase
to use for testing.这篇关于在一个控制器模拟服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!