Imagine this simple scenario: I have a class called MyModel:
public class MyModel
{
public string Prop01 { get; set; }
public string Prop02 { get; set; }
public string Prop03 { get; set; }
public bool IsValid()
{
if (String.IsNullOrEmpty(Prop01) || String.IsNullOrEmpty(Prop02) || String.IsNullOrEmpty(Prop03))
return false;
return true;
}
}
As, you can see, if any of the properties on MyModel is null or empty, the IsValid() method will return false, in other words, all the fields are "required".
I wrote some Unit Tests to test the IsValid() method:
[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
var myModel = new MyModel();
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
var myModel = new MyModel();
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
var myModel = new MyModel();
Assert.AreEqual(myModel.IsValid(), false);
}
Of course all those tests will pass, but I'm not quite happy with that. Let's imagine I'm a developer that saw the MyModel_Invalid_When_Prop01_Is_Null test (that was writen by another developer). I would expect that just by assigning a value to the Prop01 of myModel, the test should start failing. But of course it won't happen, so I changed the tests to look like this:
[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
var myModel = new MyModel();
myModel.Prop02 = "Some value";
myModel.Prop03 = "Some value";
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
var myModel = new MyModel();
myModel.Prop01 = "Some value";
myModel.Prop03 = "Some value";
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
var myModel = new MyModel();
myModel.Prop01 = "Some value";
myModel.Prop02 = "Some value";
Assert.AreEqual(myModel.IsValid(), false);
}
Now the tests are really testing that each of the properties are filled, but if I add a Prop04 to MyModel, that is also required field, I would need to change all my Unit Tests again, so I don't think this is a good idea.
So my question is: How can I unit test multiple required properties in a way that I'm sure the test is either passing or failing because of that specific property I'm currently testing? Or maybe, Should I be testing those scenarios?
Instead of starting with an empty, invalid model, you could start with a valid one and then make it invalid. That will make sure you only have to modify your tests in one place, which is fine, because your actual requirements changed.
An added advantage is that your tests become more explicit, because the setup is explicitly making your model invalid:
[TestMethod]
public void MyModel_Invalid_When_Prop01_Is_Null()
{
var myModel = getValidModel();
myModel.Prop01 = null;
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop02_Is_Null()
{
var myModel = getValidModel();
myModel.Prop02 = null;
Assert.AreEqual(myModel.IsValid(), false);
}
[TestMethod]
public void MyModel_Invalid_When_Prop03_Is_Null()
{
var myModel = getValidModel();
myModel.Prop03 = null;
Assert.AreEqual(myModel.IsValid(), false);
}
MyModel getValidModel() =>
new MyModel
{
Prop01 = "Some value",
Prop02 = "Some value",
Prop03 = "Some value",
};
If your model initialization becomes more complex, you could make use of the builder pattern. I wrote a blog-post about this which may be helpful: https://www.kenneth-truyers.net/2013/07/15/flexible-and-expressive-unit-tests-with-the-builder-pattern/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With