10

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

Tom Squires
  • 17,695
  • 11
  • 67
  • 88

3 Answers3

18

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.

Péter Török
  • 46,427
  • 16
  • 160
  • 185
3

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

O.C.
  • 149
  • 1
3

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:

https://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.

maple_shaft
  • 26,401
  • 11
  • 57
  • 131
  • 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