3

私の apicontroller では、 base.user を使用して、ルックアップで使用する認証済みユーザーを識別します。現在、これの単体テストを書いていますが、apicontroller.user をモックする方法がわかりません。リクエストを作成してそこにユーザーを設定する必要がありますか? または、controller.user を設定する別の方法はありますか?

これが私のコントローラーです。私はすでにリポジトリとメンバーシップサービスを嘲笑しています。

[Authorize]
public class DocumentController : ApiController
{
    DocumentRepository _repository;
    IStaticMembershipService _membership;

    public IEnumerable<Document> GetDocuments()
    {
        MembershipUser userAccount = _membership.GetUser(base.User);
        IEnumerable<Document> docs = null;

        if (userAccount != null)
        {
            docs = _repository.GetDocumentsByUserId(
                (Guid) userAccount.ProviderUserKey);
        }

        return docs;
    }

これが私の単体テストです:

[TestClass]
public class DocumentControllerWebService
{
    private DocumentsContext _context;
    private DocumentRepository _repository;
    private DocumentController _controller;
    private FakeMembershipService _membership;
    private TestContext testContextInstance;

    [TestInitialize]
    public void MyTestInitialize()
    {
        // Create a context with a fake data set provider
        _context = new DocumentsContext(new FakeDbSetProvider());
        _repository = new DocumentRepository(_context);
        _membership = new FakeMembershipService();
        _controller = new DocumentController(_repository, _membership);
    }

    public void GetDocumentsTest()
    {
        string userName = "someUser";
        MembershipUser userAccount = _membership.GetUser(userName);
        Guid userId = (Guid) userAccount.ProviderUserKey;
        Guid anotherUserId = Guid.NewGuid();

        // Get some dummy data and insert it into the fake repository
        List<Document> forms = DocumentDummyData.GetListOfDummyData(
            userId, anotherUserId);
        forms.ForEach(f => _repository.InsertDocument(f));

        // I would like to do this but User is readonly
        _controller.User = userName;

        List<Document> docs = _controller.GetDocuments().ToList();
        foreach (Document expected in forms.Where(d => d.UserId == userId))
        {
            Document actual = docs.Where(
                d => d.DocumentID == expected.DocumentID).FirstOrDefault();
            Assert.IsNotNull(actual);
            Assert.AreEqual(expected.DocumentID, actual.DocumentID);
        }
    }
}
4

1 に答える 1

0

http Requestからユーザーを取得している場合は、それをモックアウトする方法を検討する必要があります。ありがたいことに、それは何度も行われてきました。始めるのに良い場所はこれを読むことです

http://www.codethinked.com/post/2008/12/04/Using-SystemWebAbstractions-in-Your-WebForms-Apps.aspx

これに続いて私がしたことを要約すると、ハンゼルマンのブログといくつかの試行錯誤:

ApiControllerで、これをコンストラクターに追加します

HttpContextWrapper = HttpContextFactory.GetHttpContext();

工場はこちら

public static class HttpContextFactory
{
    [ThreadStatic]
    private static HttpContextBase _mockHttpContext;
    public static void SetHttpContext(HttpContextBase httpContextBase)
    {
        _mockHttpContext = httpContextBase;
    }

    public static HttpContextBase GetHttpContext()
    {
        if (_mockHttpContext != null)
        {
            return _mockHttpContext;
        }

        if (HttpContext.Current != null)
        {
            return new HttpContextWrapper(HttpContext.Current);
        }
        return null;
    }
}

これで、モックリクエスト、レスポンス、セッションなどを挿入できるシームができました。

HttpContextBase httpContext = HttpMocks.HttpContext();
HttpContextFactory.SetHttpContext(httpContext);

最後に、これは私が使用するかなり完全にモックされたコンテキストです

public class HttpMocks
{
    public static HttpContextBase HttpContext()
    {
        var context = MockRepository.GenerateMock<HttpContextBase>();
        context.Stub(r => r.Request).Return(HttpRequest());
        context.Stub(r => r.Response).Return(HttpResponse());
        context.Stub(r => r.Session).Return(HttpSession());
        context.Stub(r => r.Server).Return(HttpServer());
        return context;
    }

    private static HttpServerUtilityBase HttpServer()
    {
        var httpServer = MockRepository.GenerateMock<HttpServerUtilityBase>();
        httpServer.Stub(r => r.MapPath("")).IgnoreArguments().Return("");
        return httpServer;
    }

    private static HttpResponseBase HttpResponse()
    {
        var httpResponse = MockRepository.GenerateMock<HttpResponseBase>();
        var cookies = new HttpCookieCollection {new HttpCookie("UserContext")};
        httpResponse.Stub(r => r.Cookies).Return(cookies);

        Func<string, string> returnWhatWasPassed = x => x;
        httpResponse.Stub(r => r.ApplyAppPathModifier(""))
            .IgnoreArguments().Do(returnWhatWasPassed);

        return httpResponse;
    }

    public static HttpRequestBase HttpRequest()
    {
        var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
        var cookies = new HttpCookieCollection
        {
            new HttpCookie("UserContext")
        };
        httpRequest.Stub(r => r.Cookies).Return(cookies);

        var parameters = new NameValueCollection
        {
            { "id", "277" },
            { "binderId", "277" }
        };
        httpRequest.Stub(r => r.Params).Return(parameters);
        httpRequest.Stub(r => r.ApplicationPath).Return("/");
        httpRequest.Stub(r => r.AppRelativeCurrentExecutionFilePath)
            .Return("~/");
        httpRequest.Stub(r => r.PathInfo).Return("");

        var serverVariables = new NameValueCollection();
        httpRequest.Stub(r => r.ServerVariables).Return(serverVariables);

        return httpRequest;
    }

    public static HttpSessionStateBase HttpSession()
    {
        var s =  new FakeSessionState();
        s["mocking"] = "true";
        return s;
    }
}

これはかなり長い答えになりますが、何かについてもっと詳細が必要な場合は、おそらく今のところ偽のセッションを無視することができます。

于 2012-09-25T16:51:15.300 に答える