Search code examples
c#unit-testingnsubstitute

Trying to Create a Return on Chained Methods with NSubstitute and Getting Null


I have one line of code in a method that I need to set a return value for to make sure the overall method's unit test passes whether the new line of code passes or fails (it's in a try-catch block).

Here's the (names-altered) line of code:

await _serviceFactory.GetUserService().Method1(user, new List<Item>(), true)

GetUserService() returns an instance of UserService class. Method1 returns a Task<Variable> (it's in a try-catch block so in unit testing I'm having it return either Task<Variable> or an Exception to make sure overall method works for either case). The test setup for the above includes the following:

//mock to use for _serviceFactory
_mockServiceFactory = Substitute.For<IServiceFactory>();
_mockUserService= Substitute.For<UserService>
_mockServiceFactory.GetUserService().Returns(_mockUserService);

These are set in a method that gets called in Setup()

I have the following in the Arrange section of my test method: If the test case is saying Method1 should return an exception, the following:

_mockUserService.Method1(user, new List<Item>(), true)
            .Returns(Task.FromException<Variable>(new Exception()));

else

_mockUserService.Method1(user, new List<Item>(), true)
        .Returns(Task.FromResult(new Variable()));

When debugging the test, the line of code I'm trying to add and set the method's return value returns null, regardless of whether I set the return value to Task<Variable> or an Exception in the test itself.

So

await _serviceFactory.GetUserService().Method1(user, new List<Item>(), true)

is returning null when running the test. What am I missing in my setup? I figure it's that when Method1's return value is set, it is separate from when the GetUserService() return value is set and they're disconnected. I'm spinning wheels and any help is appreciated.


Solution

  • In Method1, the second parameter is new List<Item>(). When I'm setting up what this method should return with the given parameters in the test, it's getting a new List<Item>(). However, when the test runs and Method1 is actually hit, a new List<Item>() is generated and doesn't match the List<Item> setup in the test, hence why it's returning null.

    The fix was to change new List<Item>() as the second parameter to Arg.Any<List<Item>>()

    Also, for anyone who caught my first setup that is trying to return an exception, that should use .Throws and not .Returns.