The main purpose of SemanticComparison is that it allows for the easy comparison of objects. There are other ways to do this comparison but today it helped me in not having to pollute my production code.
Consider the following code:
What I want to draw your attention is that the fact that the ErrorResult class doesn’t contain any properties while the CreateReportResult class does.
Now I have a Parser class for which I wrote the following unit test:
What I’m testing is whether the result of the “Parse” is of type “CreateReportResult” and if that’s the case, then the properties of the latter should be initialised properly.
However, the fact that the “FilePath”, “PatientId” and “DataSource” are not declared on the Interface IResult means that the code won’t compile.
A hack would be to change the test and instead of using “IResult” we’d be using “CreateReportResult”. That would be wrong because, we are specifically testing that the return of the “Parse” method should be an object of type “CreateReportResult”. Hence, that part of the test would always pass i.e. a false positive.
Another solution would be to define these properties on the interface but that would mean that I would also have to create them in the “ErrorResult” class. Doing so would certainly make the code compile and the tests to work correctly. However, that for me was not a good solution because that would mean that my tests were forcing me to amend the production code for reasons other than product functionality.
Thankfully, I found SemanticComparison which allows me to do two things:
- Write my tests without side effects on my production code.
- Ensure that my tests are more robust to addition of properties.
So here is the resulting code:
The code on line 9 sets up the expected result from the constructor and then in our assertions we are doing object comparison and that’s all there is to it.
Now the test will fail if any of the properties doesn’t match. However, I have been unable to work out how to set things up so that I am told which property is causing the error and that would have been a very useful feature.