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.