Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have a class with one public method Send() and a few private methods. It calls a couple of webservices and processes the reponse. The processing is done in private methods.

I want to unit test the code. My understanding is that unit tests should test my code in isolation (ie mock up supplier responses).

I also believe that private methods should not need to be unit tested But if I just test the Send() method my code isnt being tested in isolation and is dependent on the supplier resonse.

Should I then make my private methods public so I can test them with mock responses? It seems bad practice since I only the class should need to call them.

Apologies if its a basic question, im fairly new to unit testing.

Im using c# and VS2010

share|improve this question
    
If you don't test a private method, how do you know if it works? –  Bryan Oakley Sep 23 '11 at 12:41
1  
@BryanOakley you don't need to know that a private method works, it's private. You know that it works because the public methods that call it pass their tests. –  StuperUser Sep 23 '11 at 13:24
    
@Bryan Oakley have a look at the link –  Tom Squires Sep 23 '11 at 13:49
    
Hi Tom, I've updated the link to make it more prominent and have the link text reflect its target. Please feel free to rollback. –  StuperUser Sep 23 '11 at 14:06

3 Answers 3

up vote 17 down vote accepted

You should separate the code dealing with the web services (i.e. sending and receiving data) from the code processing the results. Move the latter code into a distinct class, making the necessary methods public. Then you can easily unit test the processing logic, in isolation from the external dependencies.

By this, you also make your code conform to the Single Responsibility Principle. As a general rule of thumb, feeling the need to test private methods is often an indication that the class has too many responsibilities, thus should be refactored into multiple classes.

share|improve this answer
    
That makes a lot of sence. Thanks –  Tom Squires Sep 23 '11 at 8:52

As others have stated, if your unit tests have external dependencies like web services or database calls then they are NOT unit tests at all, they are integration tests.

True unit tests can run independently of outside components aside from the component they are intended to test and should be repeatable regardless of environment. If the outside web services go down, your unit test should not fail.

We get around this by using a Mocking Framework. Mock objects allow us to create a mock of a component so that the component in our unit test uses these mock objects instead of real ones. We can inject mock objects into the testable component, and specify what argument(s) we are expecting, what we would like it to return when it is called, even what exception we would like it to throw. I highly recommend reading more on the subject as it will improve the reliability and independence of your unit tests.

For a good post on different C# mocking frameworks see the following SO thread:

http://stackoverflow.com/questions/37359/what-c-mocking-framework-to-use

EDIT: For the overtly sensitive, I will own that I did neglect to mention DbUnit or other transactional tools that can rollback database changes at the end of the test. These are also repeatable and can be environment agnostic with generated test data thus a Mocking Framework is not needed in this case.

share|improve this answer
    
Can someone explain the downvote? I didn't rip on PHP, ROR, NoSQL databases, Javascript on the server, Apple products or any other fab trend yet I STILL got a drive-by downvote anyway :S –  maple_shaft Sep 23 '11 at 13:06
    
I guess someone didn't like having their unit tests being called "not unit tests at all" (wasn't me) :) –  Daniel B Sep 23 '11 at 13:53

I think a test with such dependencies (calling suppliers webservices) is an integration test rather than a unit test.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.