Ответ 1
Я слышал, что это полезно в Unit Testing по сравнению с Web Forms. но как это полезно?
Возьмем пример действия контроллера ASP.NET MVC, добавляющего cookie к ответу:
public class HomeController : Controller
{
public ActionResult Index()
{
var cookie = new HttpCookie("foo", "bar");
this.Response.Cookies.Add(cookie);
return View();
}
}
Обратите внимание на свойство Response. Это a HttpResponseBase
. Поэтому мы можем издеваться над ним в unit test:
public class HttpResponseMock: HttpResponseBase
{
private HttpCookieCollection cookies;
public override HttpCookieCollection Cookies
{
get
{
if (this.cookies == null)
{
this.cookies = new HttpCookieCollection();
}
return this.cookies;
}
}
}
public class HttpContextMock: HttpContextBase
{
private HttpResponseBase response;
public override HttpResponseBase Response
{
get
{
if (this.response == null)
{
this.response = new HttpResponseMock();
}
return this.response;
}
}
}
и теперь мы могли бы написать unit test:
// arrange
var sut = new HomeController();
var httpContext = new HttpContextMock();
sut.ControllerContext = new ControllerContext(httpContext, new RouteData(), sut);
// act
var actual = sut.Index();
// assert
Assert.AreEqual("bar", sut.Response.Cookies["foo"].Value);
И так как все участники виртуальны, мы могли бы использовать насмешливую структуру, которая бы не требовала написать эти макетные классы для unit test. Например, NSubstitute здесь, как может выглядеть тест:
// arrange
var sut = new HomeController();
var context = Substitute.For<HttpContextBase>();
var response = Substitute.For<HttpResponseBase>();
var cookies = new HttpCookieCollection();
context.Response.Returns(response);
context.Response.Cookies.Returns(cookies);
sut.ControllerContext = new ControllerContext(context, new RouteData(), sut);
// act
var actual = sut.Index();
// assert
Assert.AreEqual("bar", sut.Response.Cookies["foo"].Value);
Теперь давайте возьмем WebForm:
protected void Page_Load(object sender, EventArgs)
{
var cookie = new HttpCookie("foo", "bar");
this.Response.Cookies.Add(cookie);
}
В этом случае свойство Response является конкретным HttpResponse
. Итак, вы разорены. Невозможно unit test изолировать.