HttpContext.User をモックする方法 質問する

HttpContext.User をモックする方法 質問する

私は Asp.net MVC 5 プロジェクトに取り組んでおり、コントローラー内でカスタム プリンシパルを返すためのモックを設定しようとしています。検索して、提案されたさまざまなアプローチを試しましたが、どれも機能しません。

すべてのコントローラーが継承する BaseController があります。BaseController には、ゲッターで HttpContext.User を返す User プロパティがあります。HttpContext.user は、プロジェクト内で呼び出されると値を返しますが、ユニット テスト プロジェクトから呼び出されると null を返します。

ベースコントローラ

public class BaseController : Controller
{
    protected virtual new CustomPrincipal User
    {
        get { return HttpContext.User as CustomPrincipal; }  ***<== Line with issue***
    }
}

カスタムプリンシパル

public class CustomPrincipal : IPrincipal, ICustomPrincipal
{
    public IIdentity Identity { get; private set; }

    public string UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public bool   IsStoreUser { get; set; }

    public CustomPrincipal(string username)
    {
        this.Identity = new GenericIdentity(username);
    }
}

コントローラ

public class DocumentsController : BaseController
    {
        public ViewResult ViewDocuments()
        {
            var userType = User.IsStoreUser ? UserType.StoreUser : UserType.Corporate;  ***<== User is null when calling from a unit test.***
        }
    }

テストケース

[Test]
public void ViewDocuments_WhenCalled_ShouldReturnViewModel()
{
    // Arrange
    var principal = new CustomPrincipal("2038786");
    principal.UserId = "2038786";
    principal.FirstName = "Test";
    principal.LastName = "User";
    principal.IsStoreUser = true;

    var _mockController = new Mock<DocumentsController>(new UnitOfWork(_context)) { CallBase = true };
        _mockController.Setup(u => u.User).Returns(principal);  ***<== Error - "Invalid setup on a non-virtual (overridable in VB) member: u => u.User"***

    // Act
    var result = _controller.ViewDocuments();
}

nUnit と Moq を使用してモック オブジェクトを作成していますが、何が間違っているのかわかりません。テストで作成したカスタム プリンシパル オブジェクトの IsStore の値を返すには、DocumentControl の User.IsStore の戻りをモックする必要があります。

ベストアンサー1

模擬HTTPコンテキストを作成する

private class MockHttpContext : HttpContextBase {
    private readonly IPrincipal user;

    public MockHttpContext(IPrincipal principal) {
        this.user = principal;
    }

    public override IPrincipal User {
        get {
            return user;
        }
        set {
            base.User = value;
        }
    }
}

それに応じてテストを調整します。

[Test]
public void ViewDocuments_WhenCalled_ShouldReturnViewModel() {
    // Arrange
    var principal = new CustomPrincipal("2038786");
    principal.UserId = "2038786";
    principal.FirstName = "Test";
    principal.LastName = "User";
    principal.IsStoreUser = true;

    var mockUoW = new Mock<IUnitOfWork>();
    //...setup UoW dependency if needed
    var controller = new DocumentsController(mockUoW.Object);
    controller.ControllerContext = new ControllerContext {
        Controller = controller,
        HttpContext = new MockHttpContext(principal)
    };

    // Act
    var result = controller.ViewDocuments();

    //Assert
    //...assertions
}

テスト対象のシステムをモックしないでください。その依存関係をモックしてください。

おすすめ記事