43

ここでいくつかの回答を読みました:ビューとコントローラーのテスト、およびモックですが、セッション値(またはその他のコンテキストベースの変数)を読み取って設定するASP.NETMVCコントローラーをテストする方法を理解できません。テストメソッドに(セッション)コンテキストを提供するにはどうすればよいですか?答えをあざけるのですか?誰か例がありますか?基本的に、コントローラーメソッドを呼び出してコントローラーにそのセッションを使用させる前に、セッションを偽造したいと思います。何か案は?

4

7 に答える 7

44

コントローラ コンテキストの偽装に関する Stephen Walther の投稿をご覧ください。

ASP.NET MVC のヒント #12 – コントローラー コンテキストの偽装

[TestMethod]
public void TestSessionState()
{
    // Create controller
    var controller = new HomeController();


    // Create fake Controller Context
    var sessionItems = new SessionStateItemCollection();
    sessionItems["item1"] = "wow!";
    controller.ControllerContext = new FakeControllerContext(controller, sessionItems);
    var result = controller.TestSession() as ViewResult;


    // Assert
    Assert.AreEqual("wow!", result.ViewData["item1"]);

    // Assert
    Assert.AreEqual("cool!", controller.HttpContext.Session["item2"]);
}
于 2008-10-26T18:03:30.387 に答える
14

ASP.NET MVC フレームワークは、インターフェイスの代わりに抽象基本クラスを使用しているため、あまりモックに適していません (または、適切にモックするにはセットアップが多すぎて、テスト時に摩擦が多すぎます)。リクエストごとおよびセッションベースのストレージの抽象化を作成できたことは幸運でした。これらの抽象化を非常に軽量に保ち、コントローラーはリクエストごとまたはセッションごとのストレージをそれらの抽象化に依存します。

たとえば、フォーム認証を管理する方法は次のとおりです。ISecurityContext があります。

public interface ISecurityContext
{
    bool IsAuthenticated { get; }
    IIdentity CurrentIdentity { get; }
    IPrincipal CurrentUser { get; set; }
}

次のような具体的な実装を使用します。

public class SecurityContext : ISecurityContext
{
    private readonly HttpContext _context;

    public SecurityContext()
    {
        _context = HttpContext.Current;
    }

    public bool IsAuthenticated
    {
        get { return _context.Request.IsAuthenticated; }
    }

    public IIdentity CurrentIdentity
    {
        get { return _context.User.Identity; }
    }

    public IPrincipal CurrentUser
    {
        get { return _context.User; }
        set { _context.User = value; }
    }
}
于 2008-10-06T22:02:43.617 に答える
10

MVC RC 1 では、ControllerContext は HttpContext をラップし、それをプロパティとして公開します。これにより、モッキングがはるかに簡単になります。Moq でセッション変数をモックするには、次のようにします。

var controller = new HomeController();
var context = MockRepository.GenerateStub<ControllerContext>();
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue");
controller.ControllerContext = context;

詳細については、 Scott Gu の投稿を参照してください。

于 2009-02-17T18:00:56.237 に答える
5

あざけることはかなり簡単であることがわかりました。moq を使用して httpContextbase (リクエスト、セッション、およびレスポンス オブジェクトを含む) をモックする例を次に示します。

[TestMethod]
        public void HowTo_CheckSession_With_TennisApp() {
            var request = new Mock<HttpRequestBase>();
            request.Expect(r => r.HttpMethod).Returns("GET");     

            var httpContext = new Mock<HttpContextBase>();
            var session = new Mock<HttpSessionStateBase>();

            httpContext.Expect(c => c.Request).Returns(request.Object);
            httpContext.Expect(c => c.Session).Returns(session.Object);

            session.Expect(c => c.Add("test", "something here"));            

            var playerController = new NewPlayerSignupController();
            memberController.ControllerContext = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), playerController);          

            session.VerifyAll(); // function is trying to add the desired item to the session in the constructor
            //TODO: Add Assertions   
        }

それが役立つことを願っています。

于 2008-10-06T22:59:48.573 に答える
2

私は次の解決策を使用しました-他のすべてのコントローラーが継承するコントローラーを作成します。

public class TestableController : Controller
{

    public new HttpSessionStateBase Session
    {
        get
        {
            if (session == null)
            {
                session = base.Session ?? new CustomSession();
            }
            return session;
        }
    }
    private HttpSessionStateBase session;

    public class CustomSession : HttpSessionStateBase
    {

        private readonly Dictionary<string, object> dictionary; 

        public CustomSession()
        {
            dictionary = new Dictionary<string, object>();
        }

        public override object this[string name]
        {
            get
            {
                if (dictionary.ContainsKey(name))
                {
                    return dictionary[name];
                } else
                {
                    return null;
                }
            }
            set
            {
                if (!dictionary.ContainsKey(name))
                {
                    dictionary.Add(name, value);
                }
                else
                {
                    dictionary[name] = value;
                }
            }
        }

        //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs.

    }

}

次に、次のようにコードを使用します。

public class MyController : TestableController { }
于 2012-03-25T13:31:15.157 に答える
2

Scott Hanselman は、 MVC を使用してファイル アップロードのクイック アプリを作成する方法についての投稿を行い、モーキングについて説明し、具体的には「モックに適していないものをモックする方法」に対処しています。

于 2008-10-06T22:22:14.683 に答える
0

HttpContext は静的であるため、Typemock Isolator を使用してモックを作成します。Typemock には、 Ivonnaと呼ばれるASP.NET 単体テスト用にカスタム ビルドされたアドインもあります。

于 2009-04-24T09:01:13.973 に答える