How do you test private methods with NUnit?
Solution 1
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.
Solution 2
While I agree that the focus of unit testing should be the public interface, you get a far more granular impression of your code if you test private methods as well. The MS testing framework allows for this through the use of PrivateObject and PrivateType, NUnit does not. What I do instead is:
private MethodInfo GetMethod(string methodName)
{
if (string.IsNullOrWhiteSpace(methodName))
Assert.Fail("methodName cannot be null or whitespace");
var method = this.objectUnderTest.GetType()
.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
if (method == null)
Assert.Fail(string.Format("{0} method not found", methodName));
return method;
}
This way means you don't have to compromise encapsulation in favour of testability. Bear in mind you'll need to modify your BindingFlags if you want to test private static methods. The above example is just for instance methods.
Solution 3
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.
Solution 4
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 behavioural errors. Rhino.Mocks is a popular free mocking framework which will essentially 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.
Solution 5
I'm in favor of having the capability to test private methods. When xUnit started it was intended for testing functionality after the code was written. Testing the interface is sufficient for this purpose.
Unit testing has evolved to test-driven development. Having the capability to test all methods is useful for that application.
Related videos on Youtube
MrFox
Updated on July 08, 2022Comments
-
MrFox almost 2 years
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 test code 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?
-
MrFox over 15 yearsYou 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 over 15 yearsSome 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.
-
andy almost 14 years+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 almost 14 years+ 1 yep! I've just come to that conclusion while writing my tests, good advice!
-
the_joric over 12 years@MrFox actually all private logic is exposed to outer world by public methods, so eventually you can cover all it via tests for public API of your class. However decoupling might be better option if private logic is adding too much cyclomatic complexity to your class.
-
Jim D'Angelo over 12 yearsBy testing private methods, it seems you are making it harder to complete the whole TDD cycle: red->green->refactor. If I have to keep altering my tests to refactor, I am wasting time and I'm not sure I would be able to really trust those tests. I know not everybody who writes unit tests uses TDD, but you're still causing more pain when you need to refactor.
-
user1039513 over 12 yearsCould you give an example of having to alter your tests? I don't understand your point.
-
TrueWill almost 12 yearsIt is possible to test internal methods, not private (with NUnit).
-
Johan Larsson over 11 yearsTesting those small helper methods captures the unit part in unit testing. Not all are suitable for utility classes either.
-
Droj over 11 yearsThis is exactly what I needed. Thanks! All I needed was to check that a private field was getting set properly, and I DIDN'T need to spend 3 hours to figure out how to determine that via the public interface. This is existing code that can't be refactored on a whim. It's funny how a simple question can be answered with idealistic dogma...
-
Quango over 11 yearsI disagree completely with this argument. Unit testing is not about the class, it's about the code. If I had a class with one public method, and ten private ones used to create the result of the public one, I have no way of ensuring each private method works in the intended way. I could try to create test cases on the public method that hit the right private method in the right way. But I then have no idea whether the private method was actually called, unless I trust the public method to never change. Private methods are intended to be private to production users of code, not the author.
-
harpo over 11 years@Quango, in a standard testing setup, the "author" is a production user of the code. Nevertheless, if you don't smell a design problem, you have options for testing non-public methods without altering the class.
System.Reflection
allows you to access and invoke non-public methods using binding flags, so you could hack NUnit or set up your own framework. Or (easier, I think), you could set up a compile-time flag (#if TESTING) to change the access modifiers, allowing you to use existing frameworks. -
Thomas N about 11 yearsMoving private methods that you want to test but not expose to users of the API to a different class that is not exposed and make them public there is exactly what I was looking for.
-
Anders Forsgren over 10 yearsA private method is an implementation detail. A lot of the point of having unit tests is to allow for refactoring of the implementation without changing the behavior. If private methods become so complicated that one would like to cover them with tests individually, then this lemma can be used: "A private method can always be a public (or internal) method of a separate class". That is, if a piece of logic is sufficiently advanced to be subject to testing, it is probably candidate for being its own class, with its own tests.
-
bavaza over 10 yearsThis should be the selected answer, as it is the only one which actually answers the question.
-
chesterbr about 10 yearsAgreed. The chosen answer has its merits, but is the answer to "should I test private methods", not the OP's question.
-
Andrew MacNaughton over 9 yearsthanks @morechilli. Had never seen InternalsVisibleTo before. Made testing much easier.
-
Aleadam over 9 yearsHi. Recently received some down votes with no comments. Please provide some feedback to explain your thoughts or concerns.
-
Daniel Macias over 8 yearsSo if you have a private method that's being called in multiple places within a class to do something very specific only needed by that class and it's not to be exposed as part of the public API... you're saying put it in a helper class just to test? You might as well just make it public for the class.
-
Aleadam over 8 yearsIt's been 7 years since I wrote this answer...looking at it now I would say that statefulness is another interesting consideration. An alternative to moving the method to a helper class would be to ensure that the method is static thus removing it's ability to mutate state in the object and therefore maybe removing the concerns about making it public (often the move to the helper class would have led to this same change). Then the decision becomes one of cleanliness for the API.
-
Able Johnson over 8 yearsit works .Thanks! This is what many people are searching for.This should be the selected answer,
-
Gucu112 over 6 yearsSeems that cockroach is hidden inside your example code ;) Method inside NUnit's fixture must be public, otherwise you get
Message: Method is not public
. -
Maxim Kitsenko over 6 years@Gucu112 Thanks. I fixed it. In general it doesn't matter since the goal is to show aproach from the design pov.
-
Trevor almost 6 yearsGood answer this is how I would deal with a brown field project where there are no tests and you can't yet back the code with a unit test because of this scenario so start refactoring, move code into a public method in a helper class and back that class with an interface if you need to for DI. This can then be tested (I like nunit here).
-
Kyle Strand over 5 years@AndersForsgren But the point of unit testing, as opposed to integration or functional testing, is precisely to test such details. And code-coverage is considered an important unit-testing metric, so in theory every piece of logic is "sufficiently advanced to be subject to testing".
-
lamont over 2 yearsre: "A private method can always be a public (or internal) method of a separate class". If you change it to public then someone can call it externally and depend upon it and it is no longer an implementation detail. You can't change its behavior without modifying a public API, so the approach is no longer remotely equivalent under encapsulation. But sometimes it is important to test and get the implementation details correct since testing the composition of something which is very complicated doesn't always guarantee that the edge cases of the subcomponents are sufficiently explored.
-
Luke over 2 yearsNB: There is no package or namespace visibility in C#. The closest thing is internal visibility.