2016-10-25 3 views
2

私はAsp.net MVC 5プロジェクトで作業しています。コントローラ内でカスタムプリンシパルを返すようにモックをセットアップしようとしています。私は検索して、別のアプローチを試してみましたが、どれもうまくいきません。HttpContext.Userを模擬する方法

私はすべての私のコントローラが継承するBaseControllerを持っています。 BaseControllerには、getterのHttpContext.Userを返すUserプロパティがあります。 HttpContext.userはプロジェクト内で呼び出されたときに値を返しますが、単体テストプロジェクトからの呼び出しではnullを返します。

BaseController

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のと部品番号を使用していますが、私が間違ってやっている私はわかりません。テストで作成したカスタムプリンシパルオブジェクトのIsStoreの値を返すには、DocumentControlでUser.IsStoreの戻り値を嘲笑する必要があります。

答えて

1

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; 
     } 
    } 
} 

はそれに応じてテストを配置モックHTTPコンテキストを作成します。

[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 
} 

テスト中のシステムをモックしないでください。その依存関係を模倣する。

+0

Nkosiありがとう、これは素晴らしい作品です。あなたの助けと提案に感謝します。 –

0

HttpContextに直接依存しないと、もっと簡単になります。 IUserProviderインターフェイスを作成し、HttpContext(たとえばHttpContextUserProvider)に依存する実装を作成し、テストでIUserProviderをスタブします。

IUserProviderは、依存関係注入によってコントローラに渡されます。

+0

Stijn、私の質問にお返事いただきありがとうございます。あなたはあなたが示唆しているものの例を持っていますか?私は可能な限り私のコードを単純化/リファクタリングすることに常に関心を持っています。ありがとう。 –

+0

@EdmandLooi今週末に例を挙げようとします。私が忘れてしまった場合は、1週間かそこらでもう一度私にpingすることができます:) – Stijn

関連する問題