Jonn
Jonn

Reputation: 4661

How do you specify that a method can only be called by unit tests?

How do you restrict users from calling methods that are only intended for unit tests? I was thinking of throwing an exception if the call wasn't made in the context of a unit test but I don't know if tests have symbols like the "DEBUG" for projects built under debug.

One instance where I could use this is with DTOs and their identities. To properly simulate a persisted DTO I would need to assign an Id to the entity I will be using. I could do this by adding a method or adding a constructor for that specific purpose but I want it to be clear that assigning an Id to a entity should only be available for unit tests and should never be done on the actual code itself.

Upvotes: 2

Views: 662

Answers (2)

Péter Török
Péter Török

Reputation: 116306

In general, it is not recommended to have methods only meant to be called from unit tests. Ideally, the code under test should not behave differently in unit tests than in the real world. That said, sometimes such tricks are inevitable, e.g. when trying to write tests for legacy code which has never been designed to be unit testable.

Even in these case, a "test only" method should be a temporary shortcut rather than a long term solution. So I wouldn't worry so much about detecting whether the method is called from outside unit tests. Rather, once I have the code well covered with tests, strive to refactor it to get rid of "test only" methods and other temporary scaffolding, working towards a cleaner and safer design.

If you tell more about what your method is actually meant for, we may be able to give more concrete advice.

The recommmended reading on this topic is Working Effectively with Legacy Code.

Update

Thanks for your explanation. We also have such checks in a couple of places within our legacy project, so I know sometimes it's inevitable. Luckily, we didn't need to write unit tests for those places as yet (well, I would be most happy if those were the only places in our code without unit tests :-).

I thought up an alternative solution: extract the entity ID check into a separate (virtual) method (possibly in a separate interface) and override/mock that in unit tests. This way you can eliminate the need for test-only methods with only a few lines of extra code. Hope this helps :-)

Upvotes: 6

Marc Gravell
Marc Gravell

Reputation: 1063964

If the scenario demands it, adding an [asembly:InternalsVisibleTo(...)] attribute (specifying the details of the test assembly) can allow your test code to access normally private methods etc; however, this is best avoided when possible.

MSDN has an example

Upvotes: 3

Related Questions