Hot answers tagged

125

When you write unit tests for A, you mock X Do you? I don't, unless I absolutely have to. I have to if: X is slow, or X has side effects If neither of these apply, then my unit tests of A will test X too. Doing anything else would be taking isolating tests to an illogical extreme. If you have parts of your code using mocks of other parts of your code, ...


79

You need both. Unit tests to verify behavior of each of your units, and a few integration tests to make sure they're connected correctly. The problem with relying only on integration testing is combinatorial explosion resulting from interactions between all your units. Let's say you have class A, that requires 10 unit tests to fully cover all paths. Then ...


73

When you write unit tests for A, you mock X. In other words, while unit testing A, you set (postulate) the behaviour of X's mock to be X1. Time goes by, people do use your system, needs change, X evolves: you modify X to show behaviour X2. Obviously, unit tests for X will fail and you will need to adapt them. Woah, wait a moment. The implications of the ...


72

I believe this is one of the cases where using reset() is ok. The test you are writing is testing that "some things" triggers a single call to someMethod(). Writing the verify() statement with any different number of invocations can lead to confusion. atLeastOnce() allows for false positives, which is a bad thing as you want your tests to always be correct. ...


67

Instead of initializing the reader from your method, move this line { this.reader = new ReaderImplementation(this.location) } Into the default parameterless constructor. public ReaderConsumer() { this.reader = new ReaderImplementation(this.location) } public ReaderConsumer(IReader reader) { this.reader = reader } There is no such thing as a ...


65

the point of unit tests is to test units of code in isolation. Martin Fowler on Unit Test Unit testing is often talked about in software development, and is a term that I've been familiar with during my whole time writing programs. Like most software development terminology, however, it's very ill-defined, and I see confusion can often occur when people ...


54

You only need the single constructor: public class ReaderConsumer() { private IReader reader = null public string location // constructor public ReaderConsumer(IReader reader) { this.reader = reader; } in your production code: var rc = new ReaderConsumer(new ReaderImplementation(0)); in your test: var rc = new ...


48

How exactly should unit tests be written without mocking extensively? By minimising side-effects in your code. Taking your example code, if calculator for example talks to a web API, then either you create fragile tests that rely on being able to interact with that web API, or you create a mock of it. If however its a deterministic, state-free set of ...


31

There are two issues we have to look at here. The first is that you seem to be looking at all of your tests from the unit test perspective. Unit tests are extremely valuable, but are not the only kinds of tests. Tests can actually be divided into several different layers, from very fast unit tests to less fast integration tests to even slower acceptance ...


31

If you have a piece of functionality that touches several external components, you might mock all but one to isolate and test a specific component. For example, suppose you have a function that calls a web service and then does something with a database based on the results. You could write three integration tests: a test that mocks the webservice call but ...


31

These questions are quite different in their difficulty. Let's take question 2 first. Unit tests and integration tests are clearly separated. A unit test tests one unit (method or class) and uses other units only as much as necessary to achieve that goal. Mocking may be necessary, but it is not the point of the test. An integration test tests the ...


27

It sounds like you're already doing due diligence. But ... At the most practical level, always include a good handful of both "full-loop" integration tests in your suite for your own code, and write more assertions than you think you need. In particular, you should have a handful of tests that perform a full create-read-[do_stuff]-validate cycle. [...


25

You're partially right - you shouldn't directly test private methods. The private methods on a class should be invoked by one or more of the public methods (perhaps indirectly - a private method called by a public method may invoke other private methods). Therefore, when testing your public methods, you will test your private methods as well. If you have ...


23

My first recommendation would be to not mock types you don't own. You mentioned HTable being a real pain to mock - maybe you should wrap it instead in an Adapter that exposes the 20% of HTable's features you need, and mock the wrapper where needed. That being said, let's assume we're talking about types you all own. If your mock-based tests are focused on ...


20

Fix the code to be better designed. If your tests have these issues, then your code will have worse issues when you try to change things. If you can't, then perhaps you need to be less ideal. Test against the pre and post-conditions of the method. Who cares if you're using the other 5 methods? They presumably have their own unit tests making it clear(er) ...


20

if in TDD in theory you have to write first your test suit and build your code up from it Here is your misunderstanding. TDD is not about writing a full test suite first - that's is a false myth. TDD means to work in small cycles, writing one test at a time implement only as much code as needed to make the test "green" refactor (the code and the tests) So ...


16

Mocking is the ideal solution for unit tests, and it may also be used for integration tests to improve speed, but it doesn't provide the same level of confidence as when you use an in-memory database. You should write end-to-end tests where you configure the entire application as close as possible to how it is configured production and run automated tests ...


15

The file downloader has two external dependencies: a connection to Git is where data comes in. A connection to the file system is where data goes out. To be a unit test, your test should abstract from both these collaborators - you don't want to test the Git network protocol, and you don't want to test file system code either. That leaves the behaviour of ...


15

Let me start by saying that the core premise of the question is flawed. You are never testing (or mocking) implementations, you are testing (and mocking) interfaces. If I have a real class X that implements the interface X1, I can write a mock XM that also complies with X1. Then my class A must use something that implements X1, which can either be class X ...


14

Unit Tests verify the public observable behavior of a unit of code. Distribution of this behavior to a bunch of private methods is implementation detail which you do not test. The reason is that you don't want to fail your test when changing this implementation details for some reason, most likely because you're adding more behavior. Unchanged tests are ...


13

What stumbles my mind is that... if in TDD in theory you have to write first your test suit and build your code up from it, how am I supposed to know beforehand that in order to perform my operation I'll need to use those three dependencies and that the operation will call certain operations? It's like I need to know the innards of the Subject Under Test ...


13

Look into Dependency Injection and Inversion of Control Both Ewan and RubberDuck have excellent answers. But I wanted to mention another area to look into which is Dependency Injection (DI) and Inversion of Control (IoC). Both of these approaches moves the problem you're experiencing into a framework/library so that you don't have to worry about it. Your ...


12

Yes. Use mocks and stubs to simulate the web services' expected behavior. Validate that your code functions correctly under all expected boundary values and equivalence classes. EDIT: No, you should not be manually editing the unit test with int age= 50. You should be using dependency injection so that you can easily replace the Service with a mock object....


12

I work with video recording/analytics/streaming software and we faced a very similar problem. Below was our solution, not sure how it'll work out long-term but for now it seems to work. Save input/output images as resources in your unit test project. Then have unit test verify that when a specific input is given, that specific output is produced. 9/10 ...


12

Instead of creating an Employee object directly by using new, your class Bll could use an EmployeeFactory class for this, with a method createInstance, which is injected through the constructor: class EmployeeFactory : IEmployeeFactory { public Employee createInstance(){return new Employee();} } The constructor should take the factory object ...


12

It's a matter of perspective. Writing tests for our code forces us to decouple the code. You COULD view this as "code that exists only for the tests", but I think this is misleading. What you're actually doing is decoupling your code. You are removing hard dependencies and getting rid of the headaches that come with code that news up everything it needs. ...


11

philosophically, tests that use mocks should take priority over tests that use a live endpoint I think at the very least, that's a point of current ongoing controversy amongst TDD proponents. My personal view goes beyond that to say that a mock-based test is mostly a way of representing a form of interface contract; ideally it breaks (i.e fails) if and ...


11

Short answer: It's hard. You're probably feeling like there are no good answers, and that's because there are no easy answers. Long answer: Like @ptyx says, you need system tests and integration tests as well as unit tests: Unit tests are fast and easy to run. They catch bugs in individual sections of code and use mocks to make running them possible. By ...


11

How would virtual methods help? The idea of mocking is that you rip out a class completely from your application and plug in a completely different mocked class, with the only thing in common that they both implement the same interface. Inheritance doesn't come into the game at all.


10

The Open/Closed principle is mostly about being able to change the behavior of a class without modifying it. Therefore, injecting a mocked component dependency inside a class under test does not violate it. The problem with test doubles (mock/stub) is that you basically make arbitrary assumptions regarding how the class under test interacts with its ...


Only top voted, non community-wiki answers of a minimum length are eligible