C# 如何更改Assert.Fail消息

C# 如何更改Assert.Fail消息,c#,visual-studio-2010,unit-testing,C#,Visual Studio 2010,Unit Testing,运行此测试时,我得到一个“Assert.Fail failed.Assert.AreEqual failed.Expected:。实际:” 如何在错误消息末尾不显示“Actual:”而通过或失败该测试?我在其他几个测试中使用了“Assert.Fail(ex.Message);”,因此无法直接更改消息 [TestMethod] public void TestCreateUser() { try { AsaMembership

运行此测试时,我得到一个“Assert.Fail failed.Assert.AreEqual failed.Expected:。实际:”

如何在错误消息末尾不显示“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);
       }
    }

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

更多

您甚至可以创建一些特殊的失败断言,请阅读这里的

依我看,您不需要try-catch块,只需将自定义消息添加到您的断言中即可

“实际”消息来自ex.Message

您可以执行一些字符串操作,例如:

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

添加的附加信息:单元测试(通常)应仅检查单个组件。对于这个测试,我将删除验证用户的调用,因为它应该是它自己的签入测试方法

这意味着两种测试方法
CreateUser\u IsSuccessful\u如果CreatingUserThat DoesNotExist()
ValidateUser\u验证\u如果给定正确的用户名和密码()

它比TestCreateUser方法名更具描述性,并允许您进行更细粒度的测试。然后,下一个测试可能是
CreateUser\u failures\u如果creatingexistinguser()

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

[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.");
}
    [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

       }
它自定义了错误消息并删除了不必要的笨重的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()
{
    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.");
}
    [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方法在内部执行与此非常类似的操作(尽管可能会抛出派生异常类型而不是基异常)

作为高级建议,我要说的是,对提供者进行单元测试将非常困难。我在过去创建了一个自定义的,以允许我控制输入和输出的方式重写它是一个噩梦。我需要做的是提供一个构造函数,它允许我为外部依赖项传递接口,从而允许我编写测试。当我这样做的时候,我就能够编写测试,比如

ReturnsCreatedUser\u如果创建成功()
ReturnsInvalidPassword\u如果密码无效()

断言如下:
Assert.AreEqual(MembershipCreateStatus.Success,_status);
Assert.IsNotNull(响应),

Assert.AreEqual(MembershipCreateStatus.InvalidPassword,_status)


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

您刚才不是问了这个问题吗?其他资产通过了吗?如果您看到
Assert.Fail(例如Message)的值您将看到“实际”和“预期”,因为您正在断言中传递
ex.Message
属性。实际代码应引发异常(应由tets检查),而不是测试。测试应该验证行为。尽管这种方法有助于更改异常消息,但根本不应该有try/catch。从单元测试的角度来看,这是完全错误的。我不同意你的观点。本着stackoverflow的精神,我不确定是应该直接删除答案,还是在答案回答问题时保留它。我将编辑我的答案,以提供更好的指导,因为它一直困扰着我。谢谢你的建设性评论。@taras.roshko我根据你的反馈编辑了我的答案。希望它比以前更好。谢谢你的更新。我应该补充一点,如果您想验证预期的异常,使用Assert.Throws会更好,编写Assert.AreEqual(“name”,userName,“User name mismatch”)显然更干净;而不是试图用if+Assert.faily来归档这种行为,这也是MSTest再次让我失望的地方。努尼特总是有更好的办法。