Unit tests in one class (with conditional compilation)?

I know (and agree) the usual arguments for placing unit tests in a separate assembly. Recently, however, I have been experiencing some situations where I really want to test private methods. The final logic in question is complex enough that testing public and internal interfaces is not completely performed. Testing against the class’s open interface seems overloaded, and I see several places where several tests against ordinary users will get the job easier and more efficient.

I used to deal with these situations, creating the material that I need to test protected , and creating a subclass that I can use to get it in the test environment. But this does not work so well on classes that need to be sealed . Not to mention bloating the test environment with all these forests.

So, I'm going to do this instead: put some tests in a class where they can get into private members. But do not make them from production code using '#if DEBUG`.

Does this sound like a good idea?

+6
source share
3 answers

Before anyone asks ...

The solution to the OP problem is to properly enable IoC with DI and eliminate the need to test a private method in general (as Joel Martinez noted ). As mentioned several times , unit testing of private members is not the way to go.

However , sometimes you just can’t change the code (outdated systems, the risk of hacking changes - you name it), and also can’t use tools that allow you to test private members (for example, Typemock, which is a paid product). For such cases, you can either not test at all or cut corners. Which I consider the situation of OP.


Closing discussion of closed testing methods ...

Remember that you can use reflection to access and call private members.

In my opinion, placing conditional debugs in a class is a pretty bad idea - it adds noise (like something unrelated) to the class code. Of course, this will be released, but you (and possibly other programmers) will have to deal with this on a day to day basis.

I understand that your idea may seem good on paper - a simple test wrapped in conditional debugging. But in fact, tests quickly use additional variables (they should also be placed in the class code), some utilities (additional links, custom types), the testing framework (even more links), and what not. All this must be somehow related to the class code. Put it all together and you will quickly get an invisible monster.

Are you sure you want to handle this? Especially considering that merging a simple reflection-based utility may not be that difficult.

+9
source

Everything that you are talking about can be solved only with the help of two concepts: the principle of shared responsibility and the injection of dependencies . It definitely sounds like you need to simplify your activities. Keep in mind that this does not mean that the class should offer less value, it just means that the interior should be simpler, and some functions can be delegated to other users.

+7
source

If you need to test this method regardless of the class’s public API, it sounds like a candidate for removal from the class itself.

You can say that a class depends on a private method (as is evident from the need to test it separately from the public API of the class).

If this dependency cannot be satisfied by testing a public API of only one type, then the class instead delegates this dependency to another type. You can either create an instance of this type inside, or make this type entered / allowed.

This new type may have its own unit tests, as it will publicly express what it used to be a private method.

+4
source

Source: https://habr.com/ru/post/918108/


All Articles