如何更改Assert.Fail消息

时间:2013-05-13 18:12:47

标签: c# visual-studio-2010 unit-testing

当我运行此测试时,我得到一个“Assert.Fail失败.Assert.AreEqual失败。预期:。实际:。”

如果在错误消息末尾没有“Actual:”的情况下通过或未通过此测试?我使用“Assert.Fail(ex.Message);”在其他几个测试中,我无法直接更改消息。

    [TestMethod]
    public void TestCreateUser()
    {
       try
       {
          AsaMembershipProvider prov = this.GetMembershipProvider();
          //call get user
          MembershipCreateStatus status;
          MembershipUser user = prov.CreateUser("testUserX", "12345", "test.UserX@abc.com", "", "", 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, "test.userx@abc.com");
          Assert.IsTrue(user.CreationDate==DateTime.Now);
          //TODO Asserts

       }

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

3 个答案:

答案 0 :(得分:4)

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

行,

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

更多here

您甚至可以创建一些特殊失败断言,请在此处阅读CustomAsserts

IMO,你不需要那个try-catch块,只需在你的断言中添加自定义消息

答案 1 :(得分:3)

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

这意味着两种测试方法 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", "test.UserX@abc.com", "", "", 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, "test.userx@abc.com");
    if (user.Email != "test.userx@abc.com")
        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 catch的评论(因此上面的修正)。我在测试中使用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", "test.UserX@abc.com", "", "", 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, "test.userx@abc.com");
          if (user.Email != "test.userx@abc.com")
              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 Methods正在做一些与此类似的事情(虽然可能在内部抛出派生的Exception类型而不是基类)。

作为高级别建议,我会说对提供商进行单元测试将非常困难。我过去创建了一个自定义的,以一种允许我控制输入和输出的方式重写它是一场噩梦。我必须做的是提供一个构造函数,它允许我为我的外部依赖项传递接口,以允许我编写我的测试。当我这样做然后我能够编写诸如

之类的测试

ReturnsCreatedUser_IfCreationIsSuccessful()ReturnsInvalidPassword_IfPasswordIsInvalid()

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

Assert.AreEqual(MembershipCreateStatus.InvalidPassword, _status);

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

答案 2 :(得分: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);
}