Как делают меня модульный тест действие контроллера, которое использует там Контроллер. Пользовательская переменная?

Попробуйте Скрайбирование . Это пытается быть заменой TextMate для Linux

9
задан Mark Seemann 23 November 2009 в 15:06
поделиться

2 ответа

I've been using the following Mocks with Moq to allow setting up various conditions in my unit tests. First, the HttpContextBase mock:

    public static Mock<HttpContextBase> GetHttpContextMock(bool isLoggedIn)
    {
        var context = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        var response = new Mock<HttpResponseBase>();
        var session = new Mock<HttpSessionStateBase>();
        var server = new Mock<HttpServerUtilityBase>();
        var principal = AuthenticationAndAuthorization.GetPrincipleMock(isLoggedIn);

        context.SetupGet(c => c.Request).Returns(request.Object);
        context.SetupGet(c => c.Response).Returns(response.Object);
        context.SetupGet(c => c.Session).Returns(session.Object);
        context.SetupGet(c => c.Server).Returns(server.Object);
        context.SetupGet(c => c.User).Returns(principal.Object);

        return context;
    }

Every property that might provide a useful Mock is set up in here. That way, if I need to add something like a referrer, I can just use:

Mock.Get(controller.Request).Setup(s => s.UrlReferrer).Returns(new Uri("http://blah.com/");

The "GetPrincipleMock" method is what sets up the user. It looks like this:

    public static Mock<IPrincipal> GetPrincipleMock(bool isLoggedIn)
    {
        var mock = new Mock<IPrincipal>();

        mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
        mock.Setup(i => i.IsInRole(It.IsAny<string>())).Returns(false);

        return mock;
    }

    public static Mock<IIdentity> GetIdentityMock(bool isLoggedIn)
    {
        var mock = new Mock<IIdentity>();

        mock.SetupGet(i => i.AuthenticationType).Returns(isLoggedIn ? "Mock Identity" : null);
        mock.SetupGet(i => i.IsAuthenticated).Returns(isLoggedIn);
        mock.SetupGet(i => i.Name).Returns(isLoggedIn ? "testuser" : null);

        return mock;
    }

Now, my controller setups in the tests look like this:

var controller = new ProductController();
var httpContext = GetHttpContextMock(true); //logged in, set to false to not be logged in

ControllerContext controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
controller.ControllerContext = controllerContext;

It's a little bit of verbose setup, but once you have everything in place, testing a variety of conditions becomes a lot easier.

17
ответ дан 4 December 2019 в 08:52
поделиться

Это не самое простое дело, но это можно сделать. Свойство User просто делегирует Controller.HttpContext.User. Оба свойства не являются виртуальными, доступными только для чтения, поэтому вы ничего не можете с ними поделать. Однако Controller.HttpContext делегирует ControllerBase.ControllerContext, который является доступным для записи свойством.

Таким образом, вы можете назначить Test Double HttpContextBase для Controller.ControllerContext перед выполнением вашей тестируемой системы (SUT). При использовании Moq это будет выглядеть примерно так:

var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
var httpCtxStub = new Mock<HttpContextBase>();
httpCtxStub.SetupGet(ctx => ctx.User).Returns(user);

var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtxStub.Object;

sut.ControllerContext = controllerCtx;

Затем вызовите свое действие и убедитесь, что возвращаемый результат - RedirectResult.

В этом тесте используется неявное знание о том, что при создании GenericIdentity с пустым именем он вернет false для IsAuthenticated. Вы можете сделать тест более явным, используя Mock

7
ответ дан 4 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: