Asp.net mvc MVC控制器操作单元测试的粒度

Asp.net mvc MVC控制器操作单元测试的粒度,asp.net-mvc,unit-testing,Asp.net Mvc,Unit Testing,假设我有一个动作,看起来像这样: ... var userInfo = authService.SignIn(signInModel.UserName, signInModel.Password); if (userInfo == null) { ModelState.AddModelError("", "Invalid username/password"); return RedirectToAction(MVC.Home.Index()); } var user

假设我有一个动作,看起来像这样:

...
var userInfo = authService.SignIn(signInModel.UserName, signInModel.Password);    

if (userInfo == null)
{
    ModelState.AddModelError("", "Invalid username/password");
    return RedirectToAction(MVC.Home.Index());
}

var userData = new UserData
{
    UserID = userInfo.UserID,
    Name = userInfo.Name,
    Email = userInfo.Email,
    Roles = userInfo.Roles
};

string serializedUserData = textSerializer.Serialize(userData);

formsAuthHelper.CreateAuthCookie(userInfo.UserName, serializedUserData);
...
我是否应该为每个场景编写单独的单元测试:

  • 验证Serialize方法是否调用过一次
  • 验证是否调用了CreateAuthCookie方法一次

或者我可以编写一个单单元测试来验证上述两种功能吗

我会为每个beahviour创建一个测试。一个用于验证对序列化的调用,另一个用于对CreateAuthCookie的调用

这样,如果某个调用被删除,您只需要删除相应的单元测试,而无需编辑现有的单元测试

此外,如果您以以下形式为测试使用命名约定:

void When_Calling_XXXX_With_YYYY_Then_ZZZZZ();

ZZZ部分将更具可读性

我认为这完全是个人偏好,但我将在单个单元测试中验证这两个部分

我对测试的看法是,在特定的环境下,会取得一些结果。有时,这意味着需要调用多个方法或服务来实现该结果。设置auth cookie仅在Serialize()成功时才有意义,同样,调用Serialize()的唯一原因是创建auth令牌。它们不能独立运行,因此单元测试也不应该独立运行。给定有效的用户名和密码,用户即已登录。在本例中,这意味着您验证了用户的密码,并使用必需的数据创建了一个令牌

另外,我认为在实践中,仅仅为了测试的“纯度”而做所有的设置工作是浪费时间的。另一个答案是,如果您将来重构此操作,那么更新测试的难度会很大。根据我的经验,如果你真的重写了它,这将是一个巨大的变化,你将不得不重做测试

有点离题,但这就是为什么我喜欢测试框架,因为您只进行一次设置,但测试运行程序将每个验证视为单独的测试

public class when_calling_login_with_a_valid_username_and_password
{
    Because of = () => controller.Login(...);

    It should_call_serialize = () => textSerializer.Serialize().MustHaveBeenCalled();
    It should_set_the_auth_token = () => formsAuthHelper.CreateAuthCookie().MustHaveBeenCalled()
}