views:

2345

answers:

6

I am wondering how to use NUnit correctly. First i created a separate Test-Project that uses my main project as reference. But in that case i am not able to test private methods. My guess was that i need to include my testcode into my main code?! - That doesn't seem to be the correct way to do it. (I dislike the idea of shipping code with tests in it.)

How do you test private methods with NUnit?

+8  A: 

Generally, unit testing addresses a class's public interface, on the theory that the implementation is immaterial, so long as the results are correct from the client's point of view.

So, NUnit does not provide any mechanism for testing non-public members.

harpo
You are completly right. If there is some private logic that urgently needs to be tested (because of frequnet bugs), then I sould think about decompositions rather than testing inner circuits.
MrFox
+1 I've just come up against this issue and in my case there's a "mapping" algorithm that happens in between the private and the public meaning if I were to Unit Test the public, it would actually be an integration test. In this scenario I think it trying to write the test points to a design problem in the code. in which case I should probably create a different class which performs that "private" method.
andy
+1  A: 

The main goal of unit testing is to test the public methods of a class. Those public methods will use those private methods. Unit testing will test the behavior of what is publicly available.

Maxim
+2  A: 

You don't test private functions. There are ways to use reflection to get into private methods and properties. But that isn't really easy and I strongly discourage this practice.

You simply shouldn't test anything that's not public.

If you have some internal methods and properties, you should consider either changing that to public, or to ship your tests with the app (something I don't really see as a problem).

If your customer is able to run a Test-Suite and see that the code you delivered is actually "working", I don't see this as a problem (as long as you don't give away your IP through this). Things I include in every release are test-reports and code coverage reports.

Tigraine
Some customers try to keep the budget small and start discussions on the scope of tests. It's hard to explain these people that writing test is not because you are a bad coder and do not trust your own skills.
MrFox
+5  A: 

A common pattern for writing unit tests is to only test public methods.

If you find that you have many private methods that you want to test, normally this is a sign that you should refactor your code.

It would be wrong to make these methods public on the class where they currently live. That would break the contract that you want that class to have.

It may be correct to move them to a helper class and make them public there. This class may not be exposed by your API.

This way test code is never mixed with your public code.

A similar problem is testing private classes ie. classes you do not export from your assembly. In this case you can explicitly make your test code assembly a friend of the production code assembly using the attribute InternalsVisibleTo.

morechilli
+ 1 yep! I've just come to that conclusion while writing my tests, good advice!
andy
+1  A: 

I would make the private methods package visible. That way you keep it reasonably private while still being able to test those methods. I don't agree with the people saying that the public interfaces are the only ones that should be tested. There is often really critical code in the private methods that can't be properly tested by only going through the external interfaces.

So it really boils down to if you care more about correct code or information hiding. I'd say package visibility is a good compromise since in order to access those method someone would have to place their class in your package. That should really make them think twice about whether that is a really smart thing to do.

I'm a Java guy btw, so package visiblilty might be called something entirely different in C#. Suffice to say that it's when two classes have to be in the same namespace in order to access those methods.

Fylke
+2  A: 

It is possible to test private methods by declaring your test assembly as a friend assembly of the target assembly you are testing. See the link below for details:

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx

This can be useful as it does mostly seperate your test code from your production code. I have never used this method myself as i have never found a need for it. I suppose that you could use it to try and test extreme test cases which you simply can't replicate in your test environment to see how your code handles it.

As has been said though, you really shouldn't need to test private methods. You more than likley want to refactor your code into smaller building blocks. One tip that might help you when you come to refactor is to try and think about the domain that your system relates to and think about the 'real' objects that inhabit this domain. Your objects/classes in your system should relate directly to a real object which will allow you to isolate the exact behaviour that the object should contain and also limit the objects responsibilities. This will mean that you are refactoring logically rather than just to make it possible to test a particular method; you will be able to test the objects behaviour.

If you still feel the need to test internal then you might also want to consider mocking in your testing as you are likley to want to focus on one piece of code. Mocking is where you inject an objects dependencies into it but the objects injected are not the 'real' or production objects. They are dummy objects with hardcoded behaviour to make it easier to isolate behaviroual errors. Rhiomocks is a popular free mocking framework which will esentially write the objects for you. TypeMock.NET (a commercial product with a community edition available) is a more powerful framework which can mock CLR objects. Very useful for mocking the SqlConnection/SqlCommand and Datatable classes for instance when testing a database app.

Hopefully this answer will give you a bit more information to inform you about Unit Testing in general and help you get better results from Unit Testing.