是否有其他人对内置的ASP.NET单元测试框架感到沮丧?我遇到的问题是在MVC3应用程序中连接和测试ASP.NET的成员资格提供程序。看起来数据库连接尚未建立,或者当我正常运行应用程序时,存在一组不同的规则。以下是两种情况。
1)尝试按名称查找现有用户:
单元测试 -
[TestMethod]
public void RegisterTest()
{
AccountController target = new AccountController();
RegisterModel model = new RegisterModel() { UserName = "existinguser", Email = "email@test.com", Password = "Password", ConfirmPassword = "Password" };
actual = target.Register(model);
}
来自AccountController的代码块 -
MembershipCreateStatus createStatus;
MembershipUserCollection members = Membership.FindUsersByName(model.UserName);
MembershipUser user = null;
if (members.Count > 0)
createStatus = MembershipCreateStatus.DuplicateUserName;
结果 - 当我进入这段代码时,即使我知道这个用户在系统中,成员数组也是空的。在单元测试应用程序中建立与成员资格存储的连接是否有一些技巧?我尝试使用datasource属性但没有成功。
2)尝试创建新的会员帐户: 单元测试与上面相同但是我传递的是一个尚未在系统中的新用户。当我进入控制器并进入下一行时,它给了我一个'InvalidQuestion'的membershipCreateStatus。这看起来很奇怪,因为在运行这个直播时我没有那个问题,并且可以使用该行创建帐户。
user = Membership.CreateUser(model.UserName, model.Password, model.Email, string.Empty, string.Empty, true, null, out createStatus);
提前感谢您的帮助。我真的想尝试这个测试第一种方法,但它使得使用内置测试框架变得更加困难。当然有一种方法可以连接到数据库进行所有单元测试(不为每个测试提供连接),并模拟我通过浏览器执行的相同操作。
答案 0 :(得分:3)
当您运行单元测试时,它将作为新应用程序有效运行,因此将使用自己的配置文件 - 换句话说,不是您的MVC应用程序使用的web.config。所以,如果没有更多信息,我猜你会丢失的是测试项目中app.config文件中的一个条目,用于保存您的成员资格信息的数据库的连接字符串(您可能也缺少app.config)。
如果您正在尝试采用TDD方法,则应编写单元测试,如果需要连接到数据库以运行单元测试,则可能是集成测试而不是单元测试。因为Membership类使用静态方法,所以这很困难。我建议将成员资格功能包含在自己的服务中,并使用相应的接口(例如IMembershipService),然后由IoC容器注入。出于单元测试的目的,您可以简单地模拟您创建的IMembershipService接口,而无需连接到您的数据库。
答案 1 :(得分:2)
我遇到了同样的问题。是的,看起来我的单元测试更像集成测试,但我只需要测试控制器,速度在项目的这一点上不是问题。我基本上将MVC 3项目的web.config中的所有sql成员配置和连接字符串添加到测试项目的app.config中,并且当单元测试运行时,成员资格提供程序工作。下面是我的测试项目的app.config,它是一个很好的。
<?xml version="1.0" encoding="utf-8"?>
<!--
Note: Add entries to the App.config file for configuration settings
that apply only to the Test project.
-->
<configuration>
<appSettings></appSettings>
<connectionStrings>
<add name="ApplicationServices" connectionString="mySqlServer;initial catalog=mySqlMembershipDB;persist security info=True;user id=mySqlUser;password=mySqlPassword;" providerName="System.Data.SqlClient" />
</connectionStrings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.5.0" newVersion="4.0.5.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<membership defaultProvider="AspNetSqlMembershipProvider">
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile defaultProvider="AspNetSqlProfileProvider">
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false" defaultProvider="AspNetSqlRoleProvider">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="ApplicationServices" applicationName="/" />
</providers>
</roleManager>
</system.web>
</configuration>