Home > OS >  How to mock a null response using Moq?
How to mock a null response using Moq?

Time:10-29

I'm using Moq for mocking a method call and I want to mock a null response. The Login method returns a LoginResult type.

My Login interface:

public async Task<LoginResult> Login(string userPin)

My unit test mock:

var credentialsService = new Mock<ICredentialsService>();
credentialsService.Setup(x => x.Login("1234")).ReturnsAsync((LoginResult)null);

With the above mock, I receive the following warnings:

warning 1:

Warning CS8600 Converting null literal or possible null value to non-nullable type

warning 2:

Argument of type 'ISetup<ICredentialsService, Task>' cannot be used for parameter 'mock' of type 'IReturns<ICredentialsService, Task<LoginResult?>>' in 'IReturnsResult ReturnsExtensions.ReturnsAsync<ICredentialsService, LoginResult?>(IReturns<ICredentialsService, Task<LoginResult?>> mock, LoginResult? value)' due to differences in the nullability of reference types.

How can I resolve these two warnings?

CodePudding user response:

Are you aware of the fact if you don't setup your mock then it will return null by default?

This is due to the fact that the Mock<T>() constructor uses the MockBehavior.Default value.

The MockBehavior can have the following values:

  • Strict: an exception is thrown whenever a method or property is invoked without a matching configuration
  • Loose: Moq accepts all invocations and attempts to create a valid return value
  • Default: same as Loose

So, if you would define your mock with MockBehavior.Strict then you would receive an exception if there were no Setup-Returns statements. But because the default behaviour is Loose that's why you do not need to perform any Setup-Returns calls.

CodePudding user response:

The shown example uses LoginResult but the warning shows the actual type of the expected return type to be LoginResult?. That is the cause of the conversion warning.

credentialsService.Setup(x => x.Login("1234")).ReturnsAsync((LoginResult?)null);

If using ReturnsAsync is causing issues, use Returns with the Task created manually

credentialsService
    .Setup(x => x.Login(It.IsAny<string>()))
    .Returns(s => Task.FromResult<LoginResult?>((LoginResult?)null));
  • Related