макет HttpContext.Current.Server.MapPath, используя Moq? - PullRequest
11 голосов
/ 21 марта 2011

Я тестирую мой домашний контроллер.Этот тест работал нормально, пока я не добавил новую функцию, которая сохраняет изображения.

Ниже описан метод, вызывающий проблему.

    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 всегда равен нулю.и по-прежнему выдает исключение.

    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)));
    }

Ответы [ 3 ]

13 голосов
/ 21 марта 2011

HttpContext.Current - это то, что вам никогда не следует использовать, если вы ожидаете, что ваш код будет тестироваться модульно.Это статический метод, который просто возвращает ноль, если нет веб-контекста, который является случаем модульного теста и не может быть смоделирован.Итак, один из способов реорганизации вашего кода будет следующим:

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);
        }
    }
}

Видите ли, теперь этот метод больше не зависит от какого-либо веб-контекста и может тестироваться изолированно.Вызывающий абонент должен будет пройти правильный путь.

9 голосов
/ 26 июня 2013

Я согласен с ответом Дарина, но если вам действительно нужно использовать функцию Server.MapPath, вы можете сделать что-то вроде этого

//...
var serverMock = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
serverMock.Setup(i => i.MapPath(It.IsAny<String>()))
   .Returns((String a) => a.Replace("~/", @"C:\testserverdir\").Replace("/",@"\"));
//...

При выполнении этого макет просто заменит ~ / на c: \ testserverdir \ function

Надеюсь, это поможет!

2 голосов
/ 19 сентября 2016

Иногда удобно просто посмеяться над вызовом server.MapPath. Это решение работает для меня, используя moq. Я только издеваюсь над базовым путем к приложению.

        _contextMock = new Mock<HttpContextBase>();
        _contextMock.Setup(x => x.Server.MapPath("~")).Returns(@"c:\yourPath\App");
        _controller = new YourController();
        _controller.ControllerContext = new ControllerContext(_contextMock.Object, new RouteData(), _controller);

В вашем контроллере вы можете теперь использовать Server.MapPath ("~").

...