I know this question is part of a bit of a religious war, but I have the following situation:
I have an object, Responder
that calls a method on object Updater
in response to different events. I recently separated the testing in this way: state-based tests for the Updater
method itself, and behavior-based tests for the Responder
that calls it. That is, I mock the Updater
in the Responder
tests, just to ensure that it is called.
Should I still be testing the state of the objects that are supposed to be updated in the Responder
tests and not mocking the Updater
? I like what I have done because it requires less setup and seems to better isolate the tests. However, this seems to tie the implementation and expected behavior of Responder
to Updater
. Is that too brittle? This is a simplified example.
Behavior testing simply means that we should test how an application behaves in certain situations. Often the behavior is given to us developers by our customers. They describe the functionality of an application, and we write code to meet their specifications.
Verifying that the system under test produces correct results, or that its resulting state is correct, is called state-based unit testing, while verifying that it properly invokes certain methods is called interaction-based unit testing.
Interaction-based testing is a design and testing technique that emerged in the Extreme Programming (XP) community in the early 2000's. Focusing on the behavior of objects rather than their state, it explores how the object(s) under specification interact, by way of method calls, with their collaborators.
Implementation refers to a formulated plan for a designated process. It is important for any process to have a completed plan and clear objectives. The plan usually contains several actions that need to be carried out. Each of these actions needs to be tested, which is called implementation testing.
If I did understand your question correctly you really need at least two levels of testing:
Unit tests, where you are trying to test only one class and mock all the dependencies (so in your case Updater needs to be mocked here). These tests help you develop the code (especially if you are using TDD), make sure the class behaves as designed and even document how this class is meant to behave. Pretty much every class should have unit tests. However, as you noticed even if you have 100% test coverage you have no guarantee that your program works or even starts up!
Acceptance, integration and end-to-end tests - these tests cover either the whole application or big modules and test that everything works together. In general you don't use mocks at this level (you might stub a whole module/web service though, depending on the context). These tests don't have to test every single implementation detail (and shouldn't), because this is done by unit tests. They make sure that everything is correctly wired and working together. In your case you wouldn't mock Updater here.
So to sum up I think you really need to do both to have your application properly tested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With