7 ms·
> It doesn't make sense to stub out dependencies in unit tests (unless you absolutely have to). The long string of assertions that follow this remark are quite
by rumanator 7y ago
> It doesn't make sense to stub out dependencies in unit tests (unless you absolutely have to).
The long string of assertions that follow this remark are quite wrong and misses the whole point of unit tests. You are expected to write tests that test a specific unit of software, and that unit alone. You are expected to write tests that provide well defined input parameters to your unit of software, free from side effects, and you are expected to put together combinations of those input parameters that enable you to cover an adequate amount of code paths within your unit of software. By far the best and easiest way to pull this off is by mocking interfaces.
When you start testing multiple units of software interacting or writing tests that rely on specific behaviors of external units of software them you're already testing one level above what you're supposed to be testing in the test pyramid: integration tests.
- bmm6o 7y agoExactly. I don't want to assume gp doesn't understand the difference between unit and integration tests, but I think the only alternative conclusion is they don't think there is value in unit tests. I disagree, and happily inject mock objects for testing.
- deleted 7y ago[deleted]
- UK-Al05 7y agoThe problem with unit tests + heavy mocking is that you essentially makes any sort of class reorganisation as a massive pain. I try for sociable unit tests(it's a thing), which classes that are expected to work together 100% of the time are tested together. Mock out the external dependencies(http etc) or things that are expected to change. I tend to only mock out/simulate primary ports(inputs, such http requests), and secondary ports(databases calls) for simple web apps. I may start isolating stuff for testing purposes when it can be used well independently such a piece of middleware, or things that can be used by multiple parts of a project. The main difference socaiable unit tests, and integration tests is that traditional integration tests still talk to the db.
- MaulingMonkey 7y agoWhile not GP, I'll chime in and say I find very limited value in having unit tests and integration tests covering the same ground - and that I'd almost always rather have the integration tests if I'm just going to keep one of them. There are occasions when I'll mock objects, but it's rare. Working in gamedev, maybe I'm just in an environment where the possible perf/isolation benifits of mocking for the purpouses of isolating a unit just aren't as pronounced? There are still situations where dependency injection is a wonderful decoupling tool, but I can't even remember the last time I used it exclusively for the purpouses of mocking.
- gwbas1c 7y agoPart of the problem with unit tests that mock everything is that they are very time consuming to write. Minor changes in how classes interact result in 5x the time needed to update unit tests. Furthermore, unit tests don't really test product use cases. Personally, I find testing a single class with mocking best for edge cases, error conditions, or when a class is something like a custom collection that has little outside dependencies.
- rumanator 7y ago> Part of the problem with unit tests that mock everything is that they are very time consuming to write. Minor changes in how classes interact result in 5x the time needed to update unit tests. Unit tests are supposed to verify a software unit's design contract. If a minor change breaks your design contract then either the change is not minor at all or you have more serious problems to deal with than writing unit tests.
- JackRabbitSlim 7y agoThe value of the unit test is only as good as the (mock) data you feed it. Your mocked object is great and all your units pass; A user asks for the bathroom and the bar burns down because the bathroom was never mocked. What value was added by that passing unit test?
- philwelch 7y agoI wouldn't claim that unit tests are completely sufficient; you clearly also need integration tests. But you don't need all of your tests to be integration tests; in fact that would often be needlessly expensive and annoying.
- cryptica 7y agoThere is a lot of disagreement about what is a unit test outside the realms of academia. The way I'm suggesting may lead to overlapping tests with subcomponents but I would argue that this is OK. If you have a car and you want to write a unit test for the wheel, does it make sense to stub out the tire? Or if you have a door, should you stub out the door handle in your unit test? I would say no because a good test is still about the functionality of the unit/component. Testing higher level components doesn't stop you from also writing tests for the tire or for the door handle. If the higher level components have a well abstracted interface, then you should be able to substitute any child component with any other working component later and the higher level component tests should still work without any changes required. You can even change the interface of children/sub-components; doesn't matter, the parent component tests keep working. Note that this is not true if you stub out the children, you need to keep updating the stubs.
- scaryclam 7y agoI think you've inadvertently backed up the GPs point. DI makes it impossible to have single units of work, as you are quite literally injecting other units into that unit. Mocking is all find and good, but in the case of DI, you're not mocking because you have an external interface, you're mocking because you don't have single units.
- 0x445442 7y agoOne of the best ways I've found to illuminate poor designs is to not allow the use of mocking frameworks and then see how much pain follows in the test code.
- mistahenry 7y agoLet’s say I have a newsletter generation service for a website. Users can opt of emails. I use AWE SES for sending emails. I would like to test that emails are sent unless you’ve opted out. First, I don’t know how to accomplish this without mocking / replacing the email dependency before testing, even in an integration style test. Emails cost and how would I even verify if I did send the email. Second, I really am failing to see how this is poor design and am genuinely curious. I can think of so many scenarios where some “orchestrating” service uses multiple single unit services to pull off some task. To me, mocking is incredibly useful for ensuring that you test a lot of failure cases in these scenarios by mocking to force an exception. A lot can be accomplished via integration tests rather than mocking (actually using a database for example). But to somehow suggest mocking is across the board bad seems like an illogical position
- 0x445442 7y agoInstead of relying on a mocking framework to mock the injected service, can you inject a service which implements an interface and then supply whatever type of implementation you like depending on the context you'd like to test? This is one of the neat things about Java 8 Functions. I'm not sure about what their design decisions were but effectively they backed into coding to interface vs. implementation, which used to be a solid design principle.
- discreteevent 7y agoYou say "expected/supposed to" a number of times here without ever giving a reason or mentioning what tradeoffs are involved. Who cares about the testing pyramid? Theories of software development are as ubiquitous as blog posts. Which is right and why and when?