Простой способ сделать mock HttpContext для UnitTest-ов
На днях реализовывал PerHttpRequestLifeTimeManager
для своего небольшого IoC-контейнера и поэтому хочу поделиться простым способом использовать HttpContext в покрытии тестами.
Как уже наверняка стало понятно из заголовка, в основе реализации содержится экземпляр класса HttpContext
в статическом поле HttpContext.Current
которого и содержится контекст текущего HTTP запроса. Для его эмуляции достаточно следующих строк кода:
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://any-uri.org", ""),
new HttpResponse(new StringWriter())
);
Если требуется воспроизвести контекст с авторизованным пользователем, то можем добавить Principal:
HttpContext.Current.User = new GenericPrincipal(
new GenericIdentity("username"),
new string[0]
);
Вариант с пользователем после log out:
HttpContext.Current.User = new GenericPrincipal(
new GenericIdentity(String.Empty),
new string[0]
);
Решение выше не является моим и было найдено на просторах stackoverflow, однако, оказалось как никогда кстати:
В первом методе, т.к. используется один и тот же HttpContext, возвращаются одинаковые экземпляры зависимости, а во втором, напротив - различные.
[TestClass]
public class PerHttpRequestLifetimeManagerTest
{
private FsContainer container;
public PerHttpRequestLifetimeManagerTest()
{
container = new FsContainer();
container
.For<IMapper>()
.Use<Mapper>(new PerHttpRequestLifetimeManager());
}
[TestMethod]
public void TestPerSingleHttpRequestInstancesAlwaysSame()
{
// Arrange
HttpContext.Current = new HttpContext(
new HttpRequest("", "https://github.com/FSou1/FsContainer", ""),
new HttpResponse(new StringWriter())
);
var controller = container.Resolve<Controller>();
var firstMapper = container.Resolve<IMapper>();
var secondMapper = container.Resolve<IMapper>();
// Assert
Assert.IsNotNull(controller);
Assert.IsNotNull(controller.Mapper);
Assert.IsNotNull(firstMapper);
Assert.IsNotNull(secondMapper);
Assert.AreSame(controller.Mapper, firstMapper);
Assert.AreSame(controller.Mapper, secondMapper);
}
[TestMethod]
public void TestPerMultipleHttpRequestInstancesAlwaysDifferent()
{
// Arrange
HttpContext.Current = new HttpContext(
new HttpRequest("", "https://github.com/FSou1/FsContainer", ""),
new HttpResponse(new StringWriter())
);
var firstMapper = container.Resolve<IMapper>();
HttpContext.Current = new HttpContext(
new HttpRequest("", "https://github.com/FSou1", ""),
new HttpResponse(new StringWriter())
);
var secondMapper = container.Resolve<IMapper>();
// Assert
Assert.IsNotNull(firstMapper);
Assert.IsNotNull(secondMapper);
Assert.AreNotSame(firstMapper, secondMapper);
}
}