使用Fakes的Stub和Shim对ASP.NET MVC4进行单元测试

这是一篇导航文,不是翻译。

MSDN对stub和shim的解释和使用场景演示:http://msdn.microsoft.com/en-us/library/hh549175.aspx
一个更详细的示例:http://www.richonsoftware.com/post/2012/04/05/Using-Stubs-and-Shim-to-Test-with-Microsoft-Fakes-in-Visual-Studio-11.aspx

我感兴趣的是如何对mvc项目进行测试:http://www.richonsoftware.com/post/2012/05/02/Noninvasive-Unit-Testing-in-ASPNET-MVC-A-Microsoft-Fakes-Deep-Dive.aspx
里面讲的内容分别有:

1,利用shim来重写第三方类库或系统类库的方法

[TestMethod]

public void TestLogOff()

{

    var accountController = new AccountController();

    var formsAuthenticationSignOutCalled = false;

    RedirectToRouteResult redirectToRouteResult;

 

    //Scope the detours we're creating

    using (ShimsContext.Create())

    {

        //Detours FormsAuthentication.SignOut() to an empty implementation

        ShimFormsAuthentication.SignOut = () =>

        {

            //Set a boolean to identify that we actually got here

            formsAuthenticationSignOutCalled = true;

        };

        redirectToRouteResult = accountController.LogOff() as RedirectToRouteResult;

        Assert.AreEqual(true, formsAuthenticationSignOutCalled);

    }

 

    Assert.NotNull(redirectToRouteResult);

    Assert.AreEqual("Index", redirectToRouteResult.RouteValues["Action"]);

    Assert.AreEqual("Home", redirectToRouteResult.RouteValues["controller"]);

}

2,怎么判断该用stub


[TestMethod]

public void TestLogin()

{

    string testUserName = "TestUserName";

    string testPassword = "TestPassword";

    bool testRememberMe = false;

    string returnUrl = "/foo.html";

 

    var loginModel = new LoginModel

    {

        UserName = testUserName,

        Password = testPassword,

        RememberMe = testRememberMe

    };

 

    var accountController = new AccountController();

 

    //Setup underpinning via stubbing such that UrlHelper 

    //can validate that our "foo.html" is local

    var stubHttpContext = new StubHttpContextBase();

    var stubHttpRequestBase = new StubHttpRequestBase();

    stubHttpContext.RequestGet = () => stubHttpRequestBase;

    var requestContext = new RequestContext(stubHttpContext, new RouteData());

    accountController.Url = new UrlHelper(requestContext);

 

    RedirectResult redirectResult;

    //Scope the detours we're creating

    using (ShimsContext.Create())

    {

        //Sets up a detour for Membership.ValidateUser to our mocked implementation

        ShimMembership.ValidateUserStringString = (userName, password) =>

        {

            Assert.AreEqual(testUserName, userName);

            Assert.AreEqual(testPassword, password);

            return true;

        };

 

        //Sets up a detour for FormsAuthentication.SetAuthCookie to our mocked implementation

        ShimFormsAuthentication.SetAuthCookieStringBoolean = (userName, rememberMe) =>

        {

            Assert.AreEqual(testUserName, userName);

            Assert.AreEqual(testRememberMe, rememberMe);

        };

 

        redirectResult = accountController.Login(loginModel, returnUrl) as RedirectResult;

    }

 

    Assert.NotNull(redirectResult);

    Assert.AreEqual(redirectResult.Url, returnUrl);

}

3,如何还原动态对象


[TestMethod]

public void TestInvalidJsonLogin()

{

    string testUserName = "TestUserName";

    string testPassword = "TestPassword";

    bool testRememberMe = false;

    string testReturnUrl = "TestReturnUrl";

 

    var loginModel = new LoginModel

    {

        UserName = testUserName,

        Password = testPassword,

        RememberMe = testRememberMe

    };

 

    var accountController = new AccountController();

    JsonResult jsonResult;

    //Scope the detours we're creating

    using (ShimsContext.Create())

    {

        //Sets up a detour for Membership.ValidateUser to our mocked implementation

        ShimMembership.ValidateUserStringString = (userName, password) => false;

        jsonResult = accountController.JsonLogin(loginModel, testReturnUrl);

    }

     //答案在这里

    var errors = (IEnumerable<string>)(new PrivateObject(jsonResult.Data, "errors")).Target;

    Assert.AreEqual("The user name or password provided is incorrect.", errors.First());

4,如何给请求添加上下文,及如何在请求中加入用户对象


[TestMethod]

public void TestChangePassword()

{

    string testUserName = "TestUserName";

    string testOldPassword = "TestOldPassword";

    string testNewPassword = "TestNewPassword";

 

    var changePasswordModel = new ChangePasswordModel

    {

        OldPassword = testOldPassword,

        NewPassword = testNewPassword

    };

 

    var accountController = new AccountController();

 

    //Stub HttpContext

    var stubHttpContext = new StubHttpContextBase();

    //Setup ControllerContext so AccountController will use our stubHttpContext

    accountController.ControllerContext = new ControllerContext(stubHttpContext, 

        new RouteData(), accountController);

 

    //Stub IPrincipal

    var principal = new StubIPrincipal();

    principal.IdentityGet = () =>

    {

        var identity = new StubIIdentity { NameGet = () => testUserName };

        return identity;

    };

    stubHttpContext.UserGet = () => principal;

 

    RedirectToRouteResult redirectToRouteResult;

    //Scope the detours we're creating

    using (ShimsContext.Create())

    {

        ShimMembership.GetUserStringBoolean = (identityName, userIsOnline) =>

        {

            Assert.AreEqual(testUserName, identityName);

            Assert.AreEqual(true, userIsOnline);

 

            var memberShipUser = new ShimMembershipUser();

            //Sets up a detour for MemberShipUser.ChangePassword to our mocked implementation

            memberShipUser.ChangePasswordStringString = (oldPassword, newPassword) =>

            {

                Assert.AreEqual(testOldPassword, oldPassword);

                Assert.AreEqual(testNewPassword, newPassword);

                return true;

            };

            return memberShipUser;

        };

 

        var actionResult = accountController.ChangePassword(changePasswordModel);

        Assert.IsInstanceOf(typeof(RedirectToRouteResult), actionResult);

        redirectToRouteResult = actionResult as RedirectToRouteResult;

    }

    Assert.NotNull(redirectToRouteResult);

    Assert.AreEqual("ChangePasswordSuccess", redirectToRouteResult.RouteValues["Action"]);

} 
   
上面种种,文章给的不仅仅是答案,更有思考过程,比如问题原因,可能的解决方法,以及最后给一个最优的方法,值得一读的。

你可能感兴趣的:(asp.net)