Refactoring tested code - has mocking gone wrong?

2,944 views

Published on

Mock Driven Development, or Interaction Based Testing has been gaining traction. This talk looks at some of the issues around the state based and interaction based approaches.

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,944
On SlideShare
0
From Embeds
0
Number of Embeds
705
Actions
Shares
0
Downloads
16
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Refactoring tested code - has mocking gone wrong?

  1. 1. Managing Refactoring in a Test Driven World<br />Ben Stopford<br />Royal Bank of Scotland<br />
  2. 2. “I've always been a old fashioned classic TDDer and thus far I don't see any reason to change. I don't see any compelling benefits for mockist TDD, and am concerned about the consequences of coupling tests to implementation.”<br />
  3. 3. This is about as far from the fence as Martin ever gets!!<br />Mocking, BDD, Interaction based testing. The belief is that they inhibit refactoring because of the coupling they add between test and source. This is what we will be looking at today.<br />
  4. 4.
  5. 5.
  6. 6.
  7. 7.
  8. 8.
  9. 9.
  10. 10.
  11. 11. @Test void shouldMoveCashToNewAccount(){<br /> Transfertran= new CashTransfer(5,…);<br />tran.execute(newAcc);<br />assertEqual(expected, newAcc.balance());<br />}<br />Test body that <br />Exercises the <br />Class under test<br />State based <br />assertion<br />
  12. 12. Save Button<br />Save Action<br />Validity<br />Check<br />ORM<br />DB<br />
  13. 13. Save Button<br />Save Action<br />Validity<br />Check<br />ORM<br />DB<br />
  14. 14.
  15. 15. Save Button<br />Save Action<br />Validity<br />Check<br />ORM<br />DB<br />Stub n’ State approach<br />class StubValididityCheck{<br />boolean valid(){<br /> return true;<br /> }<br />}<br />
  16. 16. Save Button<br />Save Action<br />Validity<br />Check<br />ORM<br />DB<br />
  17. 17. o = new ruleComposite(new A(…), new B(…));<br />result = o.run(user);<br />assertEqual(Result.VALID, result);<br />A<br />B<br />o = new ObjectUnderTest(stubA, stubB);<br />result = o.doSomething();<br />assertEqual(expected, result);<br />A<br />B<br />
  18. 18.
  19. 19.
  20. 20. <End-to-End Test><br />Save Button<br />Save Action<br />Validity<br />Check<br />ORM<br />DB<br />… we need to make sure all the dots tie up!<br />(else our wrapped up units might start to diverge)<br />
  21. 21.
  22. 22. This object is easy to test as it is naturally isolated.<br />This object is harder to test in isolation as it forwards calls down the stack.<br />
  23. 23.
  24. 24. A Composite Object<br />Behaviour is defined by forwarding calls to composed objects<br />Assert Here<br />No observable change in state<br />Composite<br />
  25. 25. Mocking frameworks automate the testing of the interactions between classes<br />Assert Here<br />Mock based test<br />
  26. 26. o = new RuleComposite(mockRuleA, mockRuleB);<br />check(new Expectation(){<br />oneof(mockRuleA.run(user));oneof(mockRuleB.run(user)).throws(getExep());<br />};<br />o.run(obj);<br />A<br />B<br />Interaction Based Testing<br />Rather than testing changes in state, the interaction between objects are asserted.<br />
  27. 27.
  28. 28. How does this relate to the State based testing with Stubs?<br />Both allow us to isolate the code under test.<br />In practice Mocking leads to a very different development process largely because you tend to mock at a class by class level, teasing out roles for collaborating classes.<br />
  29. 29. Mocking facilitates a different development process. <br />Collaborators do not need to be implemented for the test to pass. They are simply mocked.<br />Mocks used here. No need to develop Classes yet!<br />Develop Class and Test in a tight loop<br />
  30. 30.
  31. 31.
  32. 32.
  33. 33. Refactoring should not change the behavior of a class. Hence state based tests should not break.<br />Refactoring a class may change the way it communicates with collaborating classes, breaking interaction based tests.<br />Increased Coupling makes refactoring harder<br />Stub n’ State<br />Interaction Based Testing<br />
  34. 34. Most horror stories associated with Interaction Based Tests are a result of excessive coupling produced by poor implementation<br />Interaction Based Testing is harder. There is more metaphorical rope.<br />
  35. 35. How Mocking Can Add Unnecessary Coupling?<br />Mocking Value Objects: An orange is always an orange<br />
  36. 36. How Mocking Can Add Unnecessary Coupling<br />Complex Constructors: There’s a test trying to get out<br />
  37. 37.
  38. 38. Smaller classes / classes with little functionality increase the support burden needlessly.<br />
  39. 39. For Example the Extract Class refactor<br />Increases the number of interaction points whilst holding the functional content constant<br />
  40. 40.
  41. 41.
  42. 42.
  43. 43. You don’t need to mock everything!<br />Demarcating groups of objects with mocks and using state based testing internally good practice.<br />All interactions are mocked<br />A group of collaborating objects are isolated with mocks. Internally state based testing is used.<br />

×