Assume we have a method that validates an object before saving it to a DB. It returns back KVP something like:
public KeyValuePair<bool, List<FooErrorReason>> ValidateABar(Bar b)
{
var reasons = new List<FooErrorReason>();
if (string.IsNullOrEmpty(bar.Name))
{
reasons.Add(new FooErrorReason { PropName = "Name", Message = "The name was missing" };
}
if (string.IsNullOrEmpty(bar.OtherName))
{
reasons.Add(new FooErrorReason { PropName = "OtherName", Message = "The other name was missing" };
}
return new KeyValuePair<bool, List<FooErrorReason>(reasons.Count == 0, reasons);
}
So now I want to test that, for a missing bar.Name, the error is returned. My question is on the make up of the test, concerning what to Assert
.
public void ValidateABar_Fails_For_Missing_Name()
{
//arrange
var b = new Bar { OtherName = "Other" };
//act
var result = ValidateABar(b);
//assert
Assert.IsFalse(result.Key);
Assert.AreEqual(1, result.Value.Count);
Assert.IsTrue(result.Value.Any(x => x.PropName.Equals("Name")));
}
I have 3 Assert
calls and it has a whiff of code smell about it, but I can't quite convince myself either way.
I'm asking myself 'What do you want to test?' and I do kind of feel that I should test that this failed, but failed specifically for the property of the test.
Is it enough to just use
Assert.IsTrue(result.Value.Any(x => x.PropName.Equals("Name")));
Or should I also check that there are no other errors I have picked up along the way?
Say for example someone added another validation rule without my knowing about it, I would think I would want my tests to tell me about this the next time I ran them. As an example, let's say someone changed the method as below:
public KeyValuePair<bool, List<FooErrorReason>> ValidateABar(Bar b)
{
var reasons = new List<FooErrorReason>();
if (string.IsNullOrEmpty(bar.Name))
{
reasons.Add(new FooErrorReason { PropName = "Name", Message = "The name was missing" };
}
if (string.IsNullOrEmpty(bar.OtherName))
{
reasons.Add(new FooErrorReason { PropName = "OtherName", Message = "The other name was missing" };
}
//added this!
if (string.IsNullOrEmpty(bar.ThirdName))
{
reasons.Add(new FooErrorReason { PropName = "ThirdName", Message = "The third name was missing" };
}
return new KeyValuePair<bool, List<FooErrorReason>(reasons.Count == 0, reasons);
}
The test would now fail and I would see that this rule had been added, and amend my test accordingly (and presumably write another test to cover the new rule).
Am I taking the 'one Assert per test rule' too literally?