Reputation: 151
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
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
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
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