In some cases its obvious when one or the other is warranted in other cases its not so clear. Take the following examples:
- A method which takes two inputs, performs a calculation and returns the result.
- A method which calls a factory object's Create method, passes the newly created object to the Add method of a collection object and returns void.
- A method which calls a collection's retrieval method and returns the retrieved object.
Now example 1 is pretty straightforward:
public int Calc(int int1, int int2)
{
return int1 + int2 / int1 - int2 * int1;
)
There is no interaction with other objects so this clearly calls for state-based verification.
void CalcMethodShouldDoItsThing()
{
int expected = 1;
Calculator sut = new Calculator();
int actual = sut.Calc(1,2);
Assert.IsEqual(expected, actual);
}
Example 2 clearly causes state to change but its inaccessible without using behavior verification to observe the change.
void NewObject()
{
_objectCollection.Add(_objectFactory.Create());
}
void NewObjectShouldCreateObjectAndAddItToCollection()
{
IObjectFactory mockFactory = _mockery.NewMock<IObjectFactory>();
IObjectionCollection mockCollection = _mockery.NewMock<IObjectionCollection>();
// Mock expections for your mock framework of choice
Objector sut = new Objector(mockFactory, mockCollection);
sut.NewObject();
_mockery.Verify();
}
Example 3 is a little more tricky. It returns a value it retrieved from another object so its not clear which verification technique is more appropriate.
myObject GetIt(int objectId)
{
return _objectCollection.Retrieve(objectId);
}
All three of these examples are contrived but they serve to illustrate my question. The fact that example 2's test has the word "And" in it indicates its may be doing to much even though it is a single line of code. Example 3 is simple delegation of responsibility so some may argue it doesn't need to be tested at all but it was purposefully kept simple for this question. There are far more complex examples that would have illustrated the same point.
Before anyone bothers to suggest them... yes, I've read Fowler's essay on mockist vs. classist and Gerard Mesaros' excellent xUnit Test Patterns. Both author's voice their own personal preferences and present both sides of the coin but neither delves very deeply into what to do when the choice isn't so obvious.