Ну, вы можете тестировать не на том уровне, но это тест, который имеет смысл. Я имею в виду, что если я отмечаю метод с атрибутом authorize (Roles = "Superhero"), мне не нужен тест, если я его пометил. То, что я (думаю, я) хочу, это проверить, что неавторизованный пользователь не имеет доступа и что авторизованный пользователь имеет.
Для неавторизованного пользователя такой тест:
// Arrange
var user = SetupUser(isAuthenticated, roles);
var controller = SetupController(user);
// Act
SomeHelper.Invoke(controller => controller.MyAction());
// Assert
Assert.AreEqual(401,
controller.ControllerContext.HttpContext.Response.StatusCode, "Status Code");
Ну, это нелегко, и мне потребовалось 10 часов, но вот оно. Я надеюсь, что кто-то может извлечь из этого пользу или убедить меня пойти в другую профессию. :) (Кстати - я использую носорога)
[Test]
public void AuthenticatedNotIsUserRole_Should_RedirectToLogin()
{
// Arrange
var mocks = new MockRepository();
var controller = new FriendsController();
var httpContext = FakeHttpContext(mocks, true);
controller.ControllerContext = new ControllerContext
{
Controller = controller,
RequestContext = new RequestContext(httpContext, new RouteData())
};
httpContext.User.Expect(u => u.IsInRole("User")).Return(false);
mocks.ReplayAll();
// Act
var result =
controller.ActionInvoker.InvokeAction(controller.ControllerContext, "Index");
var statusCode = httpContext.Response.StatusCode;
// Assert
Assert.IsTrue(result, "Invoker Result");
Assert.AreEqual(401, statusCode, "Status Code");
mocks.VerifyAll();
}
Хотя это не очень полезно без этой вспомогательной функции:
public static HttpContextBase FakeHttpContext(MockRepository mocks, bool isAuthenticated)
{
var context = mocks.StrictMock<HttpContextBase>();
var request = mocks.StrictMock<HttpRequestBase>();
var response = mocks.StrictMock<HttpResponseBase>();
var session = mocks.StrictMock<HttpSessionStateBase>();
var server = mocks.StrictMock<HttpServerUtilityBase>();
var cachePolicy = mocks.Stub<HttpCachePolicyBase>();
var user = mocks.StrictMock<IPrincipal>();
var identity = mocks.StrictMock<IIdentity>();
var itemDictionary = new Dictionary<object, object>();
identity.Expect(id => id.IsAuthenticated).Return(isAuthenticated);
user.Expect(u => u.Identity).Return(identity).Repeat.Any();
context.Expect(c => c.User).PropertyBehavior();
context.User = user;
context.Expect(ctx => ctx.Items).Return(itemDictionary).Repeat.Any();
context.Expect(ctx => ctx.Request).Return(request).Repeat.Any();
context.Expect(ctx => ctx.Response).Return(response).Repeat.Any();
context.Expect(ctx => ctx.Session).Return(session).Repeat.Any();
context.Expect(ctx => ctx.Server).Return(server).Repeat.Any();
response.Expect(r => r.Cache).Return(cachePolicy).Repeat.Any();
response.Expect(r => r.StatusCode).PropertyBehavior();
return context;
}
Таким образом, вы получите подтверждение того, что пользователи, не входящие в роль, не имеют доступа. Я попытался написать тест, чтобы подтвердить обратное, но после еще двух часов копания в сантехнике mvc я оставлю это ручным тестерам. (Я кинул, когда попал в класс VirtualPathProviderViewEngine. WTF? Я не хочу, чтобы что-либо делало VirtualPath, или Provider, или ViewEngine во многом объединением трех!)
Мне любопытно, почему это так сложно в якобы «проверяемой» структуре.