Ostatnio postanowiłem także bliżej zapoznać się z frameworkiem Nsubstitute. Jest to framework do tworzenia mock'ów, dużo bardziej intuicyjny niż prezentowany w książce Moq.
Do testowania używam frameworka xUnit oraz pluginu do VisualStudio pozwalającego na uruchamianie w nim xUnitowych testów.
Do sprawnego testowania potrzebne będą 2 metody pomocnicze:
- metoda udająca zapytanie, odpowiedź oraz treść zapytania Http
- metoda porównająca dane ścieżki z nazwą kontrolera, akcji oraz dodatkowych parametrów
Pierwsze 2 metody wyglądają następująco:
using System;
using System.Web;
using Xunit;
using NSubstitute;
using System.Web.Routing;
using System.Reflection;
using Routing1;
namespace UnitTests
{
public class Tests
{
private HttpContextBase CreateHttpContext(string targetUrl = null,
string httpMethod = "Get")
{
//create the mock request
var mockRequest = Substitute.For<httprequestbase>();
mockRequest.AppRelativeCurrentExecutionFilePath.Returns(targetUrl);
mockRequest.HttpMethod.Returns(httpMethod);
//create the mock response
var mockResponse = Substitute.For<httpresponsebase>();
mockResponse.ApplyAppPathModifier(Arg.Any<string>())
.Returns(s=>s[0]);
//create the mock context, using the request and response
var mockContext = Substitute.For<httpcontextbase>();
mockContext.Request.Returns(mockRequest);
mockContext.Response.Returns(mockResponse);
return mockContext;
}
private bool TestIncomingRouteResult(RouteData routeResult,
string controller, string action, object propertySet = null)
{
Func<object, bool, object> valCompare = (v1, v2) =>
{
return StringComparer.InvariantCultureIgnoreCase
.Compare(v1, v2) == 0;
};
bool result = valCompare(routeResult.Values["controller"], controller)
&& valCompare(routeResult.Values["action"], action);
if (propertySet != null)
{
PropertyInfo[] propInfo = propertySet.GetType().GetProperties();
foreach (var p in propInfo)
{
if (!(routeResult.Values.ContainsKey(p.Name)
&& valCompare(routeResult.Values[p.Name],
p.GetValue(propertySet, null))))
{
result = false;
break;
}
}
}
return result;
}
}
}
Pierwsza metoda pozwala na przekazanie URL'a poprzez właściwość AppRelativeCurrentExecutionFilePath klasy HttpRequestBase.
Druga metoda pozwala nam przetestować samą ścieżkę.
Następnie dopisane zostały kolejne 3 metody pozwalające na sprawdzenie poprawności ścieżki, sprawdzenie błędnej ścieżki oraz metody testującej kilka przykładowych ścieżek.
private void TestRouteMatch(string url, string controller, string action,
object routeProperties = null, string httpMethod = "GET")
{
//Arrange
RouteCollection routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
//Act
RouteData result
= routes.GetRouteData(CreateHttpContext(url, httpMethod));
//Assert
Assert.NotNull(result);
Assert.True(TestIncomingRouteResult(result, controller, action, routeProperties));
}
private void TestRouteFail(string url)
{
RouteCollection routes = new RouteCollection();
RouteConfig.RegisterRoutes(routes);
RouteData result = routes.GetRouteData(CreateHttpContext(url));
Assert.True(result == null || result.Route == null);
}
[Fact]
public void TestIncomingRoutes()
{
//check for the URL that we hope to receive
TestRouteMatch("~/Admin/Index","Admin","Index");
//check that the values are baing obtained from the segments
TestRouteMatch("~/One/Two", "One", "Two");
TestRouteFail("~/Admin/Index/Segment");
TestRouteFail("~/Admin");
}
Należy pamiętać, aby do projektu z testami dodać referencję do naszego prawdziwego projektu. W nim zawiera się kalsa RouteConfig wykorzystywana w metodach pomocniczych zawierająca metodę RegisterRoutes, gdzie domyślnie powinniśmy mieć zdefiniowane wszystkie ścieżki w naszej aplikacji.
Tak przygotowane testy mogą posłużyć do bardziej skomplikowanego testowania, którego przykłady zostaną zaprezentowane w kolejnej części.

Brak komentarzy:
Prześlij komentarz