3 ms·
If you don't use mocks then won't you just end up with integration tests?
by winrid 7y ago
If you don't use mocks then won't you just end up with integration tests?
- falsedan 7y agoWho cares what they’re called as long as they’re fast and don’t crash when running at scale/fill the disk or memory
- winrid 7y agoBecause if you're not using mocks the tests get unweildy. Suddenly changing components three layers down the dependency tree breaks "unit" tests at the top. Those are the tests you just end up @ignore'ing.
- msclrhd 7y agoMock things like database access, or better yet pass the database connection via an interface and create a test version of the database access so you can create a database-like thing for your tests (e.g. an in-memory database). If you are depending on another component of the application (a lexer, a JSON class, a maths function, etc.) don't mock that because if that class breaks you want tests to fail instead of silently passing because the broken class/function was mocked. If you are depending on thirdparty libraries, don't mock those unless you have to (i.e. if you cannot run the tests). This will help avoid unexpected bugs after upgrading libraries or if supporting different versions of a library. If you are writing code for a complex infrastructure (e.g. an plugin for an IDE), try to use test-specific versions of enough of the infrastructure to get the rest functioning, and use the real versions of as much as you can. This will help pick up issues in your code when new versions of that infrastructure make changes -- you want your tests to fail in this case, as the real code would fail. Understand why your tests are breaking and address that. Use @Ignore as a last resort. If APIs or behaviour has changed, update the code and tests to reflect that. If you are supporting different versions, create version-specific compatibility layers.
- winrid 7y agoAs someone that has written thousands of tests - what I disagree with you on is when writing unit tests those application components should have their own tests. Then you can cleanly mock them. Even if they are utilities etc. Same goes for application code in the same service or whatever. Mock those calls and only test your unit of code. If you don't do this things can be fine. But at some point the code base will become unwieldy and changing code in one place will break tests all over the place. Integration tests are fine and they have their place but are not a substitute for proper unit tests.
- kstenerud 7y agoThe higher up you go in your component hierarchy, the more likely it is that you'll need a mock component to test them, but I've found that it's possible to structure your architecture such that you don't need to do it as often as you'd think. If a component is using another component simply to fetch some data it needs (VERY common in my experience), then you could restructure things such that you just pass that data into the component from outside in the first place, possibly even treating it as a simple transformer instead of an actor. There's a limit to this, of course, but keeping this principle in mind in your design also has the effect of bringing coupling to a minimum or even zero in some cases, and promoting re-use of these now completely independent components. When components don't care where or how they get their data, they become a lot simpler due to the elimination of state (implicit and explicit). Elimination of state also facilitates making functions idempotent, which massively reduces cognitive load when reasoning about a system.