0

suppose our SUT(Class A) has a dependency(IDependency) and we create stub with canned answer for some operations(Method A that return bool value).

in this manner we reveal some implementation details of SUT (SUT Using Method A) and if we want refactor the SUT without breaking the original behavior(instead of method A using method B that this method return bool value too).

according to Vladimir Khorikov book (unit testing) our test does not has resistant to refactor.

question is : does Stubs make tests fragile?

ihsan
  • 59
  • 9
  • 1
    Whenever you mock / stub / fake logic of a dependency you risk not actually matching the real behavior of it. That is just how things work. – luk2302 Oct 22 '22 at 13:50
  • The risk is where ,every time I refactor my code my tests fail because I setup method A in fixture setup not method B.my test fails but SUT work correctly(false positive) – ihsan Oct 22 '22 at 14:07

1 Answers1

0

As luk2302 mentioned. Test doubles (Mocks, stubs, fakes, etc ) increase the coupling between the test and the System Under Test. The aim of a unit test should be to test the behaviour, not the implementation (this was Kent Beck objective when he came up with TDD).

But sometimes it's easier and cheaper in the long term to replace a dependency. This is obvious when a dependency is one boundary of the component e.g. one would replace a class that calls an external system. On the other side, I would think twice before using a test double for a class that is in the same package to the one I'm testing; if they are in the same package it means thay are closely related and it's ok to test them together. It helps a lot to have a pure Domain Model that doesn't interact with the external world.

Also, if a test becomes more complex and it's not easy to understand, that's a sign that it might be covering too much and I need to start splitting things; adding test doubles and maybe moving production code to other classes/packages.

I want to emphasise that a SUT doesn't need to be a single class. Many people get this wrong nowadays, thinking that only a single class must be tested and mock everything else. Even the people that came up with the London/Mockist school of testing never suggested this approach of mocking everything.

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • I use state verification in my unit test and according to Gerard Meszaros's book (xUnit test patterns) we should care about only the end state of the SUT—not how the SUT got there. If SUT in the future refactored and used method B instead of Method A, then what actually do my tests? it tests Class A with Method A of dependency while Sut works with Method B in fact and no test failed. how can I resolve this problem? – ihsan Oct 22 '22 at 16:11
  • 1
    It's a balance. We still need test doubles. The important aspect is to use them when they are required and not, as you say, test how the SUT got there. There's no correct answer, with experience you'll get a feeling of when to use a test double or use the real implementation. A hint: any pain maintaining tests is a good indication that the current direction is not good. It's good to have a low pain threshold in this area, and not be a hero :). You've read those books, so I would say you are on the right track. – Augusto Oct 22 '22 at 16:23