Reputation: 10478
I have a basic class in C# from which I create inherited classes for databinding scenarios. You can think of it as a substitute for .NET's DataRow
class.
I want to automate testing of a typical row's lifetime, making sure that things such as object state and changes detection remains coherent throughout.
My first thought was to simply use unit test class with a method that would do multiple operations and consequent assertions, like this:
/*
For the sake of keeping this as simple as possible, let's just assume
that new instances can be created with a public constructor, as "unchanged".
*/
var row = new PocoTest(); // Derived from aforementionned base class
Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));
row.MyProperty = "this is a new value";
Assert.AreEqual(RecordStates.Modified, row.RecordState);
Assert.IsTrue(row.IsPropertyModified("MyProperty"));
row.AcceptChanges();
Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));
However, this doesn't feel right in the unit testing paradigm in which it is recommended to have only one thing at a time being tested.
So I'm kind of looking for some advice, here. Am I overthinking this? Should I just keep doing it this way? Or is there another, better and more adapted way to accomplish something like this?
Upvotes: 1
Views: 1123
Reputation: 32936
your tests should each be testing one logical thing. This may require several steps or assertions to verify. This is fine.
However your tests look to me like 3 tests. 1 which verifies that upon creation the property is unchanged, and then one which verifies that when its changed the object reflects that and then one which verifies that after accepting changes the state is unchanged again.
What have you called your test currently. I suspect that you have had trouble giving it a name, or it has a long convoluted name. Splitting it it should give you nice descriptive names.
I'd go with this:
public void WhenRowIsCreatedItShouldBeInAnUnchangedState()
{
var row = new PocoTest(); // Derived from aforementionned base class
Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));
}
public void WhenPropertyIsChangedItShouldBeInAModifiedState()
{
var row = new PocoTest(); // Derived from aforementionned base class
row.MyProperty = "this is a new value";
Assert.AreEqual(RecordStates.Modified, row.RecordState);
Assert.IsTrue(row.IsPropertyModified("MyProperty"));
}
public void WhenChangesAreAcceptedItShouldBeInAnUnchangedState()
{
var row = new PocoTest(); // Derived from aforementionned base class
row.MyProperty = "this is a new value";
row.AcceptChanges();
Assert.AreEqual(RecordStates.Unchanged, row.RecordState);
Assert.IsFalse(row.IsPropertyModified("MyProperty"));
}
Upvotes: 3
Reputation: 6212
I'll have to be controversial here - I think the "one test, one test method" is a dogma rather than a useful tool. Its a matter of whether your test is whole, complete and predictable. I'd say go with your current approach - after all what is to be gained by splitting it up and adding complexity. Your code currently has lower cyclomatic complexity than adding in an extra function call for each Assert.
Upvotes: 2