user216672
user216672

Reputation: 151

How to change the Assert.Fail message

When I run this test I get an "Assert.Fail failed. Assert.AreEqual failed. Expected:. Actual:."

How do I get this test either pass or fail without "Actual:" at the end of the error message? I use "Assert.Fail(ex.Message);" in several other test so I cant change the message directly.

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

Upvotes: 0

Views: 17127

Answers (3)

Phil Patterson
Phil Patterson

Reputation: 1262

Additional info added: Unit tests (in general) should only check a single component. For this test I would remove the call to validate user as it should be it's own check in it's own test method.

This implies two test methods CreateUser_IsSuccessful_IfCreatingUserThatDoesNotExist() ValidateUser_Authenticates_IfGivenCorrectUsernameAndPassword()

which are more descriptive then the TestCreateUser method name and allows you do do finer grained testing. The next test could then be CreateUser_Fails_IfRecreatingExistingUser().

It's difficult to give really good advice as we do not know the requirements for the project you are working on. If you must have the customized output then what I have suggested originally will work (but it's not a best practice and it feels a bit like a hack to me). The better solution is something more like this:

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

which customized the error message and removed the clunky try catch which is not necessary.

I am leaving the original output from before as the answer was accepted, but I agree with the comment that try catch shouldn't be used in this way (hence the correction above). The only time I use try catch in a test is if I am specifically testing a scenario that a specific type of exception is raised that would be raised if a business rule is violated

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

If you are wanting to funnel all your asserts through to the catch block and you want to customize the error output it could be achieved like this:

    [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

       }

and your test method will still run the Assert.Fail portion. The Assert Methods behind the scenes are doing something very similar to this (though probably throwing a derived Exception type instead of the base) internally.

As high level advice I will say that unit testing the providers will be very difficult. I've created a custom one in the past and it was a nightmare to rewrite it in such a way as to allow me to control my inputs and outputs. What I had to do was provide a constructor which allowed me to pass interfaces in for my external dependencies to allow me to write my tests. When I did that Then I was able to write tests such as

ReturnsCreatedUser_IfCreationIsSuccessful() or ReturnsInvalidPassword_IfPasswordIsInvalid()

where the asserts looked something like this: Assert.AreEqual(MembershipCreateStatus.Success, _status); Assert.IsNotNull(response);,

and

Assert.AreEqual(MembershipCreateStatus.InvalidPassword, _status);.

That is a secondary issue that you will run into when trying to test the provider. For now throwing the exceptions with the message you want will allow you to customize your message completely.

Upvotes: 4

Justin R.
Justin R.

Reputation: 24071

"Actual" is coming from the ex.Message. This is read-only.

You could do some string manipulation though, something like:

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

Upvotes: 1

illegal-immigrant
illegal-immigrant

Reputation: 8254

Well, as far as I understood, you want to specify custom fail messsage for your asserts?

OK,

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

More here

You can even create some special failing assert, read here about CustomAsserts

IMO, you do not need that try-catch block, just add custom messages to your asserts

Upvotes: 5

Related Questions