使用 Moq 模拟 HttpContext.Current.Server.MapPath?
我正在对我的家庭控制器进行单元测试。这个测试工作得很好,直到我添加了一个保存图像的新功能。
导致该问题的方法如下。
public static void SaveStarCarCAPImage(int capID)
{
byte[] capBinary = Motorpoint2011Data.RetrieveCapImageData(capID);
if (capBinary != null)
{
MemoryStream ioStream = new MemoryStream();
ioStream = new MemoryStream(capBinary);
// save the memory stream as an image
// Read in the data but do not close, before using the stream.
using (Stream originalBinaryDataStream = ioStream)
{
var path = HttpContext.Current.Server.MapPath("/StarVehiclesImages");
path = System.IO.Path.Combine(path, capID + ".jpg");
Image image = Image.FromStream(originalBinaryDataStream);
Image resize = image.GetThumbnailImage(500, 375, null, new IntPtr());
resize.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
由于调用来自单元测试,因此 HttpContext.Current 为 null 并引发异常。在阅读了 Moq 和一些关于在会话中使用 Moq 的教程后,我确信它可以完成。
到目前为止,单元测试代码已经提出,但问题是 HTTPContext.Current 始终为 null,并且仍然抛出异常。
protected ControllerContext CreateStubControllerContext(Controller controller)
{
var httpContextStub = new Mock<HttpContextBase>
{
DefaultValue = DefaultValue.Mock
};
return new ControllerContext(httpContextStub.Object, new RouteData(), controller);
}
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
controller.SetFakeControllerContext();
var context = controller.HttpContext;
Mock.Get(context).Setup(s => s.Server.MapPath("/StarVehiclesImages")).Returns("My Path");
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
HomePageModel model = (HomePageModel)result.Model;
Assert.AreEqual("Welcome to ASP.NET MVC!", model.Message);
Assert.AreEqual(typeof(List<Vehicle>), model.VehicleMakes.GetType());
Assert.IsTrue(model.VehicleMakes.Exists(x => x.Make.Trim().Equals("Ford", StringComparison.OrdinalIgnoreCase)));
}
im unit testing my home controller. This test worked fine until I added a new feature which saves images.
The method that’s causing the issue is this below.
public static void SaveStarCarCAPImage(int capID)
{
byte[] capBinary = Motorpoint2011Data.RetrieveCapImageData(capID);
if (capBinary != null)
{
MemoryStream ioStream = new MemoryStream();
ioStream = new MemoryStream(capBinary);
// save the memory stream as an image
// Read in the data but do not close, before using the stream.
using (Stream originalBinaryDataStream = ioStream)
{
var path = HttpContext.Current.Server.MapPath("/StarVehiclesImages");
path = System.IO.Path.Combine(path, capID + ".jpg");
Image image = Image.FromStream(originalBinaryDataStream);
Image resize = image.GetThumbnailImage(500, 375, null, new IntPtr());
resize.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
As the call is coming from a unit test, HttpContext.Current is null and throws an exception. After reading about Moq and some of the tutorials about using Moq with sessions, im sure it can be done.
so far this the unit test code have come up with, but the issue is HTTPContext.Current is always null, and still throws the exception.
protected ControllerContext CreateStubControllerContext(Controller controller)
{
var httpContextStub = new Mock<HttpContextBase>
{
DefaultValue = DefaultValue.Mock
};
return new ControllerContext(httpContextStub.Object, new RouteData(), controller);
}
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
controller.SetFakeControllerContext();
var context = controller.HttpContext;
Mock.Get(context).Setup(s => s.Server.MapPath("/StarVehiclesImages")).Returns("My Path");
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
HomePageModel model = (HomePageModel)result.Model;
Assert.AreEqual("Welcome to ASP.NET MVC!", model.Message);
Assert.AreEqual(typeof(List<Vehicle>), model.VehicleMakes.GetType());
Assert.IsTrue(model.VehicleMakes.Exists(x => x.Make.Trim().Equals("Ford", StringComparison.OrdinalIgnoreCase)));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您希望对代码进行单元测试,则绝对不应该使用 HttpContext.Current。它是一个静态方法,如果没有 Web 上下文(这是单元测试的情况并且无法模拟),则简单地返回 null。因此,重构代码的一种方法如下:
您看,现在此方法不再依赖于任何 Web 上下文,并且可以单独进行测试。调用者有责任传递正确的路径。
HttpContext.Current
is something that you should absolutely never use if you ever expect your code to be unit tested. It is a static method which simply returns null if there is no web context which is the case of a unit test and cannot be mocked. So one way to refactor your code would be the following:You see, now this method no longer depends on any web context and can be tested in isolation. It will be the responsibility of the caller to pass the correct path.
我同意 Darin 的答案,但如果您确实需要 moq Server.MapPath 函数,您可以执行类似的操作
执行此操作,模拟将简单地将 ~/ 替换为 c:\testserverdir\ 函数
希望它有帮助!
I agree with the Darin´s answer but if you really need to moq the Server.MapPath function you could do something like this
Performing this, the mock will simply replace the ~/ with the c:\testserverdir\ function
Hope it helps!
有时,模拟对 server.MapPath 的调用会很方便。
这个解决方案适用于我使用最小起订量。
我只模拟应用程序的基本路径。
在您的控制器中,您现在可以使用 Server.MapPath("~")。
It is sometimes handy to just mock the call to server.MapPath.
This solution works for me using moq.
I only mock the base path to the application.
In your controller you can now user Server.MapPath("~").
下面对我有用。
Below works for me.