Over Specification in Tests

I've gotten the chance to visit and consult various companies and I see this all the time: Over specification in tests, especially when doing mocks and stubs.

One main reason for that is that people use their stub as a mock object (stubs are fake objects that we will not assert on so that we can test something else). here is a small example from something posted on the alt.net mailing list:

[Test]

public void Can_Return_All_Plans()

{

IPlanDao mockPlanDao = MockRepository.GenerateMock<IPlanDao>();

mockPlanDao.Expect(x => x.AllPlans(_fakeAdmin)).Return(new List<Plan>{_fakePlan});

PlanController planController = new PlanControllerForTesting(_mockCommonDao, _mockCommonService, mockPlanDao);

ViewResult result = planController.All(false);

mockPlanDao.VerifyAllExpectations();

result.AssertViewResultNameAndViewDataType(typeof(PlanContainer), "Plans");

}

in this test the following line is used to "stub" out a return value into the system under test.

mockPlanDao.Expect(x => x.AllPlans(_fakeAdmin)).Return(new List<Plan>{_fakePlan});

no problem here. The problem lies in the last two lines of the test:

mockPlanDao.VerifyAllExpectations();

result.AssertViewResultNameAndViewDataType(typeof(PlanContainer), "Plans");

 

the second line (the assert) is probably the thing you really want to test. but the call to "verifyAllExpectations" is the one that makes the test very fragile. It is "asserting" that someone has actually called "GetAllPlans()" to get the results, when it clearly does not matter how one got the results. all that matters is that:

"Given a set of results returned into the application under test, the view in the controller is correct" (the translation of the last line in the test).

If by any chance the application later does several more calls to the stubbed out dao, or uses a different method to get results, the test could break, even though the application would still ultimately work with the same end result.

It's like me ordering a pizza delivery and then asking the delivery guy "did you get here by car or motorcycle?" . I realy don't care, as long as the end result: PIZZA, is correct.

So the general rules for me are:

  • If you see both "Verify" and "Assert" in the same test, it is usualy a smell of over specified tests
  • if you see "expect" and "Return" on a fake object, make sure that you name it "stubXX" or "mockXX" so that you can distinguish whether you want to call verify on it later or not(most cases should be "not")
  • Try to test on the end result or end state rather than verify interactions.  The only time you absolutely have not choice but to test an interaction using verify is when calling void methods on external objects. that is clearly a one-way communication and is (or part of)the end result of what you are trying to accomplish.

 

A lot of people think that adding that extra "verify" just means it is a good thing since they are doing more assert. Well, they sure are testing more things, but they are internal things to the app's behavior and that is usually leading to brittle tests. Try to test on the end result or end state rather than verify interactions.

Published Saturday, July 12, 2008 6:23 AM by RoyOsherove

Comments

Saturday, July 12, 2008 12:23 PM by Aaron Jensen

# re: Over Specification in Tests

In that particular example the real problem is the use of Expect rather than Stub. Rhino.Mocks has facilities for both, and you should use Stub unless you want to Assert on interaction.

This is yet another example of why the Expect/Verify method should be stricken from mocking frameworks. No matter how much you preach the one-assert-per-test guideline, people are just not going to understand how expect/verify fits in.

As soon as you make them add a line at the end of the test to assert a method was called their intentions become more clear and they will have been guided to doing that by choice rather than bad sample tests.

Saturday, July 12, 2008 4:32 PM by Arjan`s World » LINKBLOG for July 12, 2008

# Arjan`s World &raquo; LINKBLOG for July 12, 2008

Pingback from  Arjan`s World    &raquo; LINKBLOG for July 12, 2008

Monday, July 14, 2008 2:32 PM by ASPSmith

# re: Over Specification in Tests

Being relatively new to mocking, I'm guilty of this myself.  It's not intuitive to a new user when to use fakes, stubs, mocks, dynamic mocks, static mocks, etc etc etc.  And there is a big shift in thinking between state-based testing (x goes in, y comes out) and behavior-based testing (to do x, a, b, and c must be called, bu don't worry about what the actual result ends up being as long as that is satisfied).  I think in a lot of my tests I end up combining the two, but I can see how this can be a bad thing, resulting in overcomplicated or overly long tests.

Monday, July 14, 2008 4:00 PM by Cokin Jack

# re: Over Specification in Tests

As you say being clear about whether you are mocking or stubbing is key.

Leave a Comment

(required) 
(required) 
(optional)
(required)