somedude
somedude

Reputation: 179

C# Unit testing nested functions

I have a method that calls another method from a different class.

How should I write unit tests for these methods? Should I write different test cases for both methods or should I write test case only for LoadService.InitiateManualRun function?

An example will be very helpful.

class LoadService
{    
    public StagingLoadStatistics InitiateManualRun(string currentUser, string startDate, string endDate)
    {
        var response = _repository.InitiateManualRun(currentUser, startDate, endDate);

        return response;
    }
}

class LoadRepository
{     
    public StagingLoadStatistics InitiateManualRun(string currentUser, string startDate, string endDate)
    {
        _webServiceObject.InitiateManualRun(currentUser, startDate, endDate);
    }
}

Upvotes: 0

Views: 2242

Answers (2)

Anthony Pegram
Anthony Pegram

Reputation: 126794

Your code sample doesn't reveal much added value from your additional levels of abstraction, but I will grant that you are probably leaving out some detail for the sake of brevity.

If I am testing a function that calls into another class' function, my primary concern is that the outer function provided the expected inputs to the inner function, or the outer function performed the correct actions with the outputs from the inner function, or both. Testing the inner function is not the concern of the test of the outer function, I will have tests for that class and function on its own.

I will isolate my outer function using mocks/stubs to be sure that I am testing what I think I am testing, and any failure is going to be the result of that function doing the wrong thing, not some nested dependency. My tests for the nested dependency will reveal to me the bugs in that area.

Given your original code, I would expose my dependency

class LoadService
{    
    ILoadRepository _repository;

    public LoadService(ILoadRepository repository)
    {
         _repository = repository;
    }

    public StagingLoadStatistics InitiateManualRun(string currentUser, string startDate, string endDate)
    {
        var response = _repository.InitiateManualRun(currentUser, startDate, endDate);
        return response;
    }
}

And based off this code, my concern is simple (your actual code may differ, of course). It appears that I just need to verify that my arguments are properly passed on to my dependency and then the dependency's result is returned. That's a pretty easy test to write, but you would need to write a fake implementation of the dependency or otherwise use a mocking library. But my test might look like this:

var fakeRepository = new FakeRepository();
var expectedArguments = Tuple.Create(someUser, someStartDate, someEndDate);
var expectedOutput = new StagingLoadStatistics();
fakeRepository.SetOutputForExpectedArguments(expectedArguments, expectedOutput);

var service = new LoadService(fakeRepository);
var result = service.InitiateManualRun(someUser, someStartDate, someEndDate);
Assert.AreSame(expectedOutput, result);

Your fake can take on any number of flavors, and again you can roll your own or use a library for it. When I roll my own, I typically just use a backing dictionary inside the fake that stores the expectation and result, and then returns the result when the expectation is met. This allows multiple expectation/result pairs to be stored, if applicable. But you will want to research all your options surrounding fake implementations if you choose to go this direction for highly isolated tests.

Upvotes: 3

Ryan Gates
Ryan Gates

Reputation: 4539

You should write the unit test for the LoadService.InitiateManualRun method.

This will help verify behavior at a higher level and make for more flexible tests that won't break if you change the signature or other implementation details of the nested method. Your unit test should verify a use case or behavior of the program.

That being said, in the code that you have shared there is only a single execution branch, so I am not sure what your unit test would verify.

Upvotes: 1

Related Questions