How do you unit test a class that depends on many other classes?

I heard that with unit testing we can catch most of the bugs in the code, and I really think that is true. But my question is in large projects, where each class depends on many other classes, how do you go about unit unit testing? Stopping all other classes does not make much sense because of the complexity and time required to write the stubs. What is your opinion on this?

+4
unit testing
source share
9 answers

Part of the advantage of using tests is that it forces you to minimize dependencies, thereby creating testable code. By minimizing dependencies, you will increase maintainability and reuse of your code as very desirable traits.

Since you are introducing tests into your existing code base, you will undoubtedly encounter many difficult test situations that will require refactoring for proper validation. This refactoring will increase the testability of your code while reducing dependencies.

The reason it is difficult to modify code with tests is because many defenders follow Test-Driven-Development. If you write your tests first and then write the code to pass the tests, your default code will be much more verifiable and decoupled.

+11
source share

Use a mocking structure to drown out your classes for you. Mocking frameworks (I use Rhino Mocks for C # /. NET), it's pretty easy to drown out your dependencies. Used with dependency injection, your classes can be easily separated from other classes and do not require much work to make them so. Please note that sometimes it becomes easier to "fake" something, rather than mock. I end up pretending to be a few classes, but it's usually pretty easy to write them - they just contain "good" or "bad" data and return it. There was no logic.

+4
source share

I am not ready for a quick test of the entire unit, but I think that each unit should be a kind of test. In the test case, some procedure should be tested. The procedure may not be limited to one class.

For example, if your application can be divided into atomic components, then for each component and for each applicable chain of transitions between components, a test case may exist.

0
source share

In our project, developers are responsible for writing and maintaining stubs from the very beginning.

Despite the fact that cigarette butts take time and money, unit testing provides some undeniable advantages (and you also agreed). This allows you to automate the testing process, reduces the difficulty of detecting errors contained in more complex parts of the application, and the frequency of testing is often increased, because attention is paid to each unit.

In my experience, I saw that in projects in which we put unit testing with low priority, I had to suffer at a later stage, when one change either breaks the situation or requires additional testing.

Unit testing improves self-confidence as a software developer.

0
source share

I prefer unit test functions, which may or may not correspond to individual classes. This granularity of unit tests, in my opinion, is the best compromise in the work required for testing, customer feedback (because functions are what they pay for) and the long-term usefulness of unit tests (including requirements, practical examples illustrate)

as a result, it is rarely taunted, but some tests cover several classes

0
source share

But my question is in large projects where each class depends on many other classes, how do you go about device class testing?

First, you understand that "every class depends on many other classes" - this is bad, right? And that this is not a function of a large project, but a poor design? (This is one of the advantages of TDD, which tends to discourage such highly connected code.)

Interrupting any other class does not make sense because of both the complexity and the time required to write the stubs.

Not to mention that this does not help design problems. Worse, investing in all stubs can actually be an obstacle to refactoring, if only psychological.

The best approach (IMHO) is to start inside out at the classrooms, changing the design as you go. I usually approached this by doing what I call "internal dependency." This includes leaving the method signatures intact, but retrieving the data needed from the dependencies, and then retrieving the functions that contain the actual logic. A trivial example might be:

public int foo(A a, B b) { C c = a.getC(); D d = b.getD(); Bar bar = calculateBar(c, d); return calculateFoo(bar, this.baz); } Bar calculateBar(C c, D d) { ... } int calculateFoo(Bar bar, Baz baz) { ... } 

Now I can write a test to calculate Bar and calculateBaz, but I do not need to worry about setting up internal states (this.baz), and I do not need to worry about creating mock versions of A and B.

After creating such tests using existing interfaces, I look for an opportunity to push changes to the interface, for example, change the Foo method to use C and D, rather than A and B.

Does any of this make sense?

0
source share

You are right, and all the classes on which the tested class depends are not worth the effort. And you will also have to maintain your layout if you change the interfaces.

If the classes used by the ones you are testing have already been tested, then it is good to have a test spanning multiple classes.

Sometimes it's easier to fool an object: when

  • the object has or is using an external resource, such as a database or network connection, disk
  • object is a graphical interface
  • object not yet available
  • object behavior is not deterministic
  • road facility for installation
0
source share

I feel that you may need refactoring to reduce complexity.

I found that this can be very useful for refactoring classes (i.e. breaking them down), so each of them carries one responsibility (less complicated). Then you can unit test fulfill this responsibility. you can use mocking frameworks to easily mimic and initialize dependencies. I find FakeItEasy very good and easy to use, and you can find some good examples.

0
source share

Here are principles that have proven themselves for testing, but also for reliable design in a very large corporate project:

  • Make your dependencies explicit by taking them through class constructors.

  • Instead of taking specific classes as dependencies, create interfaces that define the necessary functions, and instead take these interfaces as dependencies on class constructors. It also allows you to apply a dependency injection pattern, if necessary.

  • Use one of the existing frameworks such as Moq, so you don’t need to write a full test implementation of your interfaces, but at runtime you create Moq objects from your unit test.

0
source share

All Articles