使用Moq模拟HttpContext.Current.Server.MapPath?
我单位测试我的家庭控制器。 此测试工作正常,直到我添加了一个保存图像的新function。
引起问题的方法如下。
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); } } }
由于调用来自unit testing,HttpContext.Current为null并抛出exception。 在阅读了Moq以及关于将Moq与会话一起使用的一些教程之后,我确信它可以完成。
到目前为止,unit testing代码已经提出,但问题是HTTPContext.Current始终为null,并且仍然抛出exception。
protected ControllerContext CreateStubControllerContext(Controller controller) { var httpContextStub = new Mock { 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), model.VehicleMakes.GetType()); Assert.IsTrue(model.VehicleMakes.Exists(x => x.Make.Trim().Equals("Ford", StringComparison.OrdinalIgnoreCase))); }
如果您希望对代码进行unit testing,那么您绝对不应该使用HttpContext.Current
。 它是一个静态方法,如果没有Web上下文就是unit testing并且无法模拟,则它只返回null。 因此,重构代码的一种方法如下:
public static void SaveStarCarCAPImage(int capID, string path) { byte[] capBinary = Motorpoint2011Data.RetrieveCapImageData(capID, path); 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) { 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); } } }
您看,现在这种方法不再依赖于任何Web上下文,可以单独测试。 调用者负责传递正确的路径。
我同意Darin的回答,但是如果你真的需要moq Server.MapPath函数,你可以做这样的事情
//... var serverMock = new Mock(MockBehavior.Loose); serverMock.Setup(i => i.MapPath(It.IsAny())) .Returns((String a) => a.Replace("~/", @"C:\testserverdir\").Replace("/",@"\")); //...
执行此操作,mock将简单地用〜:/ testserverdir \函数替换〜/
希望能帮助到你!
有时候只是模拟对server.MapPath的调用是很方便的。 这个解决方案适用于我使用moq。 我只模拟应用程序的基本路径。
_contextMock = new Mock(); _contextMock.Setup(x => x.Server.MapPath("~")).Returns(@"c:\yourPath\App"); _controller = new YourController(); _controller.ControllerContext = new ControllerContext(_contextMock.Object, new RouteData(), _controller);
在您的控制器中,您现在可以使用Server.MapPath(“〜”)。