Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing - same method but for different test data

This is pretty basic question around unit testing.

I have a method e.g. GetOrderDetails which calls a Repository to fetch order details. I have a mock repository which can be setup to return stock responses.

For testing GetOrderDetails method, I'll at least use the following cases -

Repository call fails

  1. with an error code
  2. with an Exception

Repository call succeeded

  1. returned zero result
  2. returned one result
  3. returned more than one result

Should I be writing a single Test method to test above scenarios or should it really be a seperate test method for each of the above scenario?

I believe, breaking it down into multiple test methods would at least provide the following benefits 1. higher isolation in case of test failures 2. amount of code within a test method is less 3. each test method will have a single repository setup responsibility e.g. either setup for no result, or setup for multiple results etc

Could you please help with your views around this?

like image 735
byte Avatar asked Dec 06 '10 15:12

byte


People also ask

Should unit tests only test one method?

This guideline is much more aggressive and recommended if you work in a test driven manner rather than write the tests after the code has been written. The main goal here is better code coverage or test coverage.

Do you need a unit test for every method?

The answer to the more general question is yes, you should unit test everything you can. Doing so creates a legacy for later so changes down the road can be done with peace of mind. It ensures that your code works as expected.

Can unit tests depend on each other?

Tests should never depend on each other. If your tests have to be run in a specific order, then you need to change your tests. Instead, you should make proper use of the Setup and TearDown features of your unit-testing framework to ensure each test is ready to run individually.

Should unit tests be in the same package?

Unit tests can be in any package. In essence they are just separate classes used to test the behaviour of the class being tested.


3 Answers

I would write a separate unit test for each case. Basically every time you write an if or a switch inside the method you are testing it implies different unit tests to handle each case. The reason for this is that the arrange part of your unit test will be different based on which route you would like your code to take (different mock expectations, property setups, ...). Also I would recommend you to organize your unit test in the following three parts:

// arrange
// -> prepare mock objects, properties, setup expectations

// act
// -> invoke the method your are testing

// assert
// -> assert on the results returned by the method your are testing
like image 167
Darin Dimitrov Avatar answered Nov 15 '22 10:11

Darin Dimitrov


I know some people might set up a data-driven test method that executes based on varying criteria in a data source, but I prefer individual methods, particularly since that allows me to give it a meaningful name along the lines of MethodName_StateUnderTest_ExpectedResult (a naming convention championed by agile/unit testing coach and author Roy Osherove, among others). I can look at the name and immediately know what passed or failed, not have to wonder what variation may have passed or failed. It also helps that my unit test isn't dependent upon the file system.

like image 26
Anthony Pegram Avatar answered Nov 15 '22 10:11

Anthony Pegram


This is really a subjective question and you will get varied answers. A few things to keep in mind.

  1. Keep the test code short and sweet. I try to fit all my unit test functions in one screen. If I can do that, than I put anything in there I want to. I certainly test more than one thing in a particular function as long the overlying method is short.

  2. duplicating code unit tests, with only one variable difference is a maintenance nightmare. Imagine having 5 unit tests, each containing 40 lines of code, and the only difference between them is a silly return value. If you do that, you will be scratching your head in 6 months.

  3. Use a code coverage tool while writing unit tests. I can't over emphasize that. It will help you identify areas that are you not testing. I have found it helps me eliminate dead code as well, since less code is less potential bugs.

  4. The most complicated logic I ever put in a unit test, is a for loop. And that is only to initialize a simple array, if it is needed for something specific to the test. I always steer clear of if statements in unit tests. But if are using data driven tests, a for loop is just fine to feed data into your tests, if you need to do it. But if the for loop is small, feel free to unroll the loop too.

I hope some of that advice helps.

like image 30
C Johnson Avatar answered Nov 15 '22 09:11

C Johnson