2013-05-13 109 views
0

当我运行此测试时,出现“Assert.Fail failed。Assert.AreEqual failed。Expected :. Actual :.”如何更改Assert.Fail消息

如何在错误消息结束时通过或未通过“实际:”的测试失败?我使用“Assert.Fail(ex.Message);”在其他几个测试中,所以我不能直接更改消息。

[TestMethod] 
    public void TestCreateUser() 
    { 
     try 
     { 
      AsaMembershipProvider prov = this.GetMembershipProvider(); 
      //call get user 
      MembershipCreateStatus status; 
      MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

      Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
      var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 

      Assert.IsTrue(isAuthenticated); 
      Assert.AreEqual(user.UserName, "testUserX"); 
      Assert.AreEqual(user.Email, "[email protected]"); 
      Assert.IsTrue(user.CreationDate==DateTime.Now); 
      //TODO Asserts 

     } 

     catch (Exception ex) 
     { 
      LogMessage(ex); 
      Assert.Fail(ex.Message); 
     } 
    } 
+1

你刚才问这个吗?其他断言是否通过?如果你看到'Assert.Fail(ex.Message)'的值;''你将会看到'Actual'和'Expected',因为你在断言中传递了'ex.Message'属性。 – Brian 2013-05-13 18:18:45

回答

2

附加信息添加:单元测试(一般来说)只能检查单个组件。对于这个测试,我会删除调用来验证用户,因为它应该是它自己的检查它自己的测试方法。

这意味着两种试验方法 CreateUser_IsSuccessful_IfCreatingUserThatDoesNotExist() ValidateUser_Authenticates_IfGivenCorrectUsernameAndPassword()

这是更具描述性的,则TestCreateUser方法名,并允许你做更细致的检测。接下来的测试可以是CreateUser_Fails_IfRecreatingExistingUser()

很难给出真正的好建议,因为我们不知道您正在进行的项目的要求。如果你必须有定制的输出,那么我原来建议的将会起作用(但这不是一个最佳做法,这对我来说有点像黑客)。更好的解决方案是更多的东西是这样的:

[TestMethod] 
public void TestCreateUser() 
{ 
    AsaMembershipProvider prov = this.GetMembershipProvider(); 
    //call get user 
    MembershipCreateStatus status; 
    MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

    //Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
    if (status != MembershipCreateStatus.Success) 
     Assert.Fail("Error message you want goes here for this case."); 
    var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 
    //Assert.IsTrue(isAuthenticated); 
    if (!isAuthenticated) 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.AreEqual(user.UserName, "testUserX"); 
    if (user.UserName != "testUserX") 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.AreEqual(user.Email, "[email protected]"); 
    if (user.Email != "[email protected]") 
     Assert.Fail("Error message you want goes here for this case."); 
    //Assert.IsTrue(user.CreationDate==DateTime.Now); 
    if (user.CreationDate != DateTime.Now) 
     Assert.Fail("Error message you want goes here for this case."); 
} 

其定制的错误信息和删除笨重的尝试捕捉这是没有必要的。

由于答案被接受,我将离开原来的输出结果,但我同意不应该以这种方式使用try catch(因此上述修正)。我使用的尝试捕捉在测试的唯一情况是如果我专门测试该异常的特定类型提出了一个方案,如果违反业务规则

try 
{ 
    methodToThrowException(); 
    Assert.Fail("BusinessSpecificException was not thrown by the code."); 
} 
catch (BusinessSpecificException ex) 
{ 
    //Asserts go here 
} 

如果你想要的是将提高漏斗所有的断言通过对catch块,你要自定义的错误输出它可以这样实现:

[TestMethod] 
    public void TestCreateUser() 
    { 
     try 
     { 
      AsaMembershipProvider prov = this.GetMembershipProvider(); 
      //call get user 
      MembershipCreateStatus status; 
      MembershipUser user = prov.CreateUser("testUserX", "12345", "[email protected]", "", "", true, null, out status); 

      //Assert.AreNotEqual(status, MembershipCreateStatus.Success); 
      if (status != MembershipCreateStatus.Success) 
       throw new Exception("Error message you want goes here for this case."); 
      var isAuthenticated = prov.ValidateUser(user.UserName, "12345"); 

      //Assert.IsTrue(isAuthenticated); 
      if (!isAuthenticated) 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.AreEqual(user.UserName, "testUserX"); 
      if (user.UserName != "testUserX") 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.AreEqual(user.Email, "[email protected]"); 
      if (user.Email != "[email protected]") 
       throw new Exception("Error message you want goes here for this case."); 
      //Assert.IsTrue(user.CreationDate==DateTime.Now); 
      if (user.CreationDate != DateTime.Now) 
       throw new Exception("Error message you want goes here for this case."); 
      //TODO Asserts 

     } 

和测试方法仍然会运行Assert.Fail部分。幕后的Assert方法在内部做着与此非常类似的事情(尽管可能抛出派生的Exception类型而不是基类)。

作为高层次的建议,我会说单元测试提供者将会非常困难。我在过去创建了一个自定义的,这是一个噩梦,重写它的方式,让我来控制我的输入和输出。我所要做的就是提供一个构造函数,它允许我为外部依赖项传递接口以允许我编写测试。当我这样做,然后我能写的测试,如

ReturnsCreatedUser_IfCreationIsSuccessful()ReturnsInvalidPassword_IfPasswordIsInvalid()

其中断言看起来是这样的:Assert.AreEqual(MembershipCreateStatus.Success, _status); Assert.IsNotNull(response);

Assert.AreEqual(MembershipCreateStatus.InvalidPassword, _status);

这是您尝试测试提供程序时遇到的第二个问题。现在,用你想要的信息抛出异常将允许你完全自定义你的信息。

+2

实际的代码应该抛出异常(应该由tets检查),而不是测试。测试应该验证行为。虽然这种方法可以帮助改变异常信息,但根本不应该有任何try/catch。单元测试的观点完全错误 – 2013-05-13 20:23:06

+0

我并不反对你。本着stackoverflow的精神,我不确定我是否应该直接删除答案,或者在答案时回答。我会编辑我的答案以提供更好的指导,因为它一直困扰着我。感谢您的建设性意见。 – 2013-05-14 13:26:12

+0

@ taras.roshko我根据您的反馈编辑了我的答案。希望它比以前更好。 – 2013-05-14 13:53:12

4

那么,据我所知,你想为你的断言指定自定义失败消息?

OK,

Assert.AreEqual(object expected, object actual, string message); 

here

,你甚至可以创建一些特殊的失败断言,读到这里大约CustomAsserts

IMO,你并不需要一个try-catch块,只需添加自定义消息到您的断言

1

“实际”来自ex.Message。 This is read-only

你可以做一些字符串操作虽然是这样的:

catch (Exception ex) 
{ 
    string message = ex.Message.Substring(0, ex.Message.IndexOf("Actual:")); 
    LogMessage(message); 
    Asset.Fail(ex.Message); 
}