views:

405

answers:

8

Where do you put unit tests for private functions in C# classes?

An article in Wikipedia suggests:

  • Putting tests in the same class as the members they're testing
  • Using partial classes

Personally, neither of these methods seem appropriate, and I much prefer to have unit tests located in a separate project altogether.

Any thoughts on this?

(I know there's a fair amount of debate on whether private methods should be tested at all. I'd like to hear both sides of the argument.)

+14  A: 

Private methods do not necessarily need to be tested directly. You can determine their validity based on tests of public methods that utilize those private methods.

However, you should take care to ensure that your public methods can easily inject mock dependencies into your private methods to facilitate testing and simulate all reasonable scenarios.

Edit: As for where your other tests should be located, I suggest a separate subdirectory within your project to handle your tests. When writing tests for PHP applications, I have a tests directory in the root of my project whose directory structure is identical to that of my real application directory structure. In it, I have a test class for each real class.

Just don't compile your test classes with the rest of your project when releasing to production (or in the case of an interpretted language like PHP, don't deploy the test classes to the production webserver).

Mike
+1 for phrasing it nicely. :)
Noufal Ibrahim
So are you saying that the code in private functions shouldn't have any dependencies that aren't received as parameters by the constructor of that class, or a public method?
jonathanconway
Agreed with making dependencies injectable, being able to replace any dependency simplifies testing. Receiving them through constructor or property is standard, and fits with containers. When it's just for testability purposes, you can also consider using internal methods or properties.
Mathias
@jonathanconway: Indeed. If, for example, a private method is using a database connection it should grab it from a member variable or it should have it passed as a parameter. It should not go out and instantiate it itself. If it does, you have no way to mock the DB and have it do something else for purposes of the test (perhaps simulate failure or some other condition).
Mike
Injectability of dependencies is an issue that has nothing to do with whether or not to test private methods or where to place tests.
Jason
@Jason: I never said it did. I said he should use DI to facilitate testing of his private methods via public methods. It was an addendum to my answer, not a prerequisite.
Mike
@Mike: "However, you should take care to ensure that your public methods can easily inject mock dependencies into your private methods to facilitate testing and simulate all reasonable scenarios." That says nothing about facilitating testing of private methods via public interfaces.
Jason
@Jason: Sorry if I am wrong, but it looks fine to me. :)
Mike
+1  A: 

Your question title and first sentence are different. :)

I'm not sure about where to place your tests. That would depend on language and C# is not something I'm familiar with but I imagine that a substantial part of your code is inside private methods. I'd feel uncomfortable if that was not tested. Code coverage would drop quite a bit.

Noufal Ibrahim
Sorry about the confusion; I edited the heading.
jonathanconway
+1  A: 

absolutely yes. private methods should be tested anyway. and mbunit unit test framework can access private member.

see this blog: testing private methods

Benny
+8  A: 

Do not unit test private methods. Unit tests are for testing the visible (so public and protected) interface of a class. The private methods are implementation details and writing unit tests for them is unnecessary (their behavior should be implicitly tested by the tests on the visible methods), leads to brittle tests (as the implementation details could change) and is a barrier to refactoring.

If you have a private method that you feel you need to unit test, that is a big hint that maybe it should be factored out into a public method on another class.

Where do you put unit tests for private functions in C# classes?

Nowhere. They don't exist.

In general, my unit tests are in separate projects.

Jason
That points to the aim of test: the tests says "your objects work OK", it is: "your object's public interface work OK". If fact the reason to be of your private methods are the public methods so they must exist only to implement some thing for public methods. So if you test public methods, you are testing private ones. Test Driven Development says: if you want to do something write the test and next implement it. That way you only program public that are necesary. Private methods will follow the same policy.
helios
Is Class that just has a constructor and private methods not useful to unit test?
Stein G. Strindhaug
+1  A: 

We use private accessors in Visual Studio to test private methods. This means that that the test classes can live in a separate project.

However, we try to really limit the numbers of these because:

  • a private method that can stand alone can be pulled out as a public method in another class
  • private methods that don't do anything particularly useful outside of the class can be tested through the public methods of that class
Matt Breckon
+3  A: 

I also personally like to have unit tests in a separate project. If you want to unit test a private method, you could make the private method internal instead. You can then make internal methods visible to your unit tests to call directly by adding the following to AssemblyInfo.cs:

[assembly: InternalsVisibleTo("MyAssembly.UnitTests")]
AdaTheDev
+1, but I think it is best to only test public i/f.
kenny
+2  A: 

I agree that private methods shouldn't be tested, in general, because you should only test the public interfaces.

That being said, there are reasons why you might want to test private methods:

  1. You are using TDD, and you have to develop a complex private method. Creating test methods for the private method may be necessary to keep your write test- write code - test cycle at the right granularity.

  2. You may be part of a team where others may need to modify the private method, and you want tests to ensure that the changes don't create problems.

Some solutions:

  1. Declare some methods that are public that delegate to the private method and are used only for testing purposes. These could be prefixed e.g. with TestFoo1, TestFoo2 etc.

  2. Use internal

http://msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx

Larry Watanabe
+3  A: 

You should do what works for you; here's what works for me:

My unit is a class: that's what I'm trying to test. Not a method. I'm trying to do object-oriented programming, so I put my attention on objects.

If I find myself tempted to test a private method, I need to refactor. I only want to test a private method directly because there is too much other code between it and the tests, and because the private method itself is complex enough to need testing attention. So, I'll usually Extract Class to pull that private method, and other related members in to a new class.

My classes tend to be quite small. They're easy to read and understand. My methods, of course, are also very small and easy to understand.

Making the transition to this way of working required me to rethink many of my assumptions and habits about programming. What once seemed radical now seems commonplace.

Jay Bazuzi
+1 for mentioning that if you are tempted to test a private method, you (probably) need to refactor.
Rob Levine