Consider unit tests for two (or more) consequent layers in web-application, backend, eg views (these are concerned with parsing form parameters, rendering the response) and actions (application logic). In the view, calls to actions are mocked. In the actions calls to underlying level are mocked. Tests are fast, but are less useful than they can be, because the connection between layers needs syncing and integration tests are slow and rarer (in theory). Syncing means that mock and mocked functions/methods are in sync. Otherwise we test a mock, which may easily loose connection to reality if not updated, and thus the power of unit tests is diminished.
The question is, has anyone already come with an idea how to keep upper layer mocks with lower level "interfaces" with the goal of making test more maintainable while still being fast? Less stable interfaces are of interest of course.
I always preferred functional, more integration-like tests because they tend to catch more regressions and bugs than mocked separate unit tests. In some cases, application logic is just a simple transaction script with N actions, so mocking does not provide any benefit to testing (unit test too closely follows implementation). However, those are slow, so I am trying to come with some mechanism, and maybe inventing the wheel.
Especially, in the higher level dynamic languages, like Python.
function my_script(): callA() callB() callC()
Tests will look like (pseudocode):
monkeypatch(callA, dummyA) monkeypatch(callB, dummyB) monkeypatch(callC, dummyC) my_script() assert dummyB.called_after(dummyA) assert dummyC.called_after(dummyB)
- this will not catch
callD()should that be added to my_script or side-effects inside those functions or even changes in their signatures (lest say,
callBchanged to require a parameter). The test will still pass. In this case unit test is useless.