0

MVC で単体テストを実行しようとしていますが、一部の機能では UserID が必要です (つまり、外部キーとしてデータベースに保存します)。

UserID は、ユニット テスト時に UserID を「偽造」して、偽のユーザーでユニット テストを実行できるようにする方法のUserData属性に格納されます。FormsAuthenticationTicketこれは可能ですか?

Microsoft の組み込みの単体テスト システムを使用しています。

私が使用する予定のテストコードは、

[TestMethod]
public void EnsureAddItemAddsItems()
{
   // Arrange
   ShoppingCartController controller = new ShoppingCartController();
   // These would be populated by dummy values
   Guid itemID = Guid.Empty;
   Guid itemTypeID = Guid.Empty;

   // Act
   ViewResult result = controller.AddItem(itemTypeID, itemID);

   //Assert
   Assert.AreEqual("Your shopping cart contains 1 item(s)",result.ViewBag.Message);
}

サンプルコードは次のようになります:-

public ActionResult AddItem(Guid itemType, Guid itemID, string returnAction)
{
    ShoppingCartViewModel oModel = new ShoppingCartViewModel();

    string szName = String.Empty;
    int price = 0;


    using (var context = new entityModel())
    {
        // This is the section I'm worries about
>>>>>>>>> Guid gUserID = this.GetCurrentUserID(); <<<<<<<<<

        var currentSession = this.CreateOrContinueCurrentCartSession(gUserID);

        var oItem = new ShoppingCartItem();
        oItem.Id = Guid.NewGuid();
        oItem.ItemId = itemID;
        oItem.ItemTypeId = itemType;
        oItem.ItemName = szName;
        oItem.ShoppingCartSessionId = currentSession.ID;
        oItem.Price = 1;
        context.ShoppingCartItems.AddObject(oItem);
        context.SaveChanges();
    }

    this.FlashInfo("Item added to shopping cart");
    ViewBag.Message(string.Format("Your shopping cart contains {0} item(s)",AnotherFunctionThatJustCountsTheValues()));
    return this.View();

}

強調表示された行は、userID を取得する場所です。その関数は、複雑なことを何も行わない単なる拡張関数であり、FormsAuthenticationTicket.UserDataフィールドとして保存されている UserID をフェッチするだけです。

4

1 に答える 1

4

// ここが気になるところGuid gUserID = this.GetCurrentUserID();

これは、通常、このセクションはコントローラー アクション内では何もしないためです。では、削除しましょうか。このようにして、もう何も心配する必要はありません:-)

ノイズが多すぎるため、最初にコードを単純化しましょう。ところで、コントローラ アクションは複雑すぎてあまりにも多くのことを行うため、ダイエットを検討する必要があります。

重要な部分は次のとおりです。

[Authorize]
public ActionResult AddItem()
{
    Guid gUserID = this.GetCurrentUserID();
    return Content(gUserID.ToString());
}

GetCurrentUserIDメソッドがコントローラーに存在し、フォーム認証 Cookie を読み取ろうとすると、それを単独で単体テストするのに苦労する可能性があるため、これは本当に面倒です。

コードが次のようになったらどうでしょうか。

[MyAuthorize]
public ActionResult AddItem()
{
    var user = (MyUser)User;
    return Content(user.Id.ToString());
}

MyUserカスタム プリンシパルは次のとおりです。

public class MyUser : GenericPrincipal
{
    public MyUser(IIdentity identity, string[] roles) : base(identity, roles)
    { }

    public Guid Id { get; set; }
}

それは素晴らしいことではないでしょうか。このようにして、コントローラーのアクションは Cookie やチケットなどを気にする必要がなくなります。それはその責任ではありません。

単体テストの方法を見てみましょう。お気に入りのモッキング フレームワーク (私の場合はRhino MocksとMvcContrib.TestHelper ) を選び、次のようにモックします。

[TestMethod]
public void AddItem_Returns_A_Content_Result_With_The_Current_User_Id()
{
    // arrange
    var sut = new HomeController();
    var cb = new TestControllerBuilder();
    cb.InitializeController(sut);
    var user = new MyUser(new GenericIdentity("john"), null)
    {
        Id = Guid.NewGuid(),
    };
    cb.HttpContext.User = user;

    // act
    var actual = sut.AddItem();

    // assert
    actual
        .AssertResultIs<ContentResult>()
        .Content
        .Equals(user.Id.ToString());
}

あとは、カスタム[MyAuthorize]属性がどのように見えるかを見てみましょう。

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var authorized = base.AuthorizeCore(httpContext);
        if (!authorized)
        {
            return false;
        }

        var cookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
        if (cookie == null)
        {
            return false;
        }

        var ticket = FormsAuthentication.Decrypt(cookie.Value);
        var id = Guid.Parse(ticket.UserData);
        var identity = new GenericIdentity(ticket.Name);
        httpContext.User = new MyUser(identity, null)
        {
            Id = id
        };
        return true;
    }
}

カスタム認証属性は、フォーム認証 Cookie の UserData セクションを読み取り、現在のプリンシパルをカスタム プリンシパルに設定する役割を果たします。

于 2012-07-13T13:07:04.293 に答える