Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Mock returns null when an object is expected

I have a test that looks like this.

namespace Domain.Tests.Unit.Features.ForUser.Auth
{
    [TestClass]
    public class LoginHandlerTests
    {
        [TestMethod]
        public async Task Should_Succeede_With_Valid_User()
        {
            // Arrange
            var loginCommand = new LoginHandler.LoginCommand
            {
                Email = "testemail",
                Password = "testpassword"
            };
            
            var user = new User
            {
                Email = loginCommand.Email,
                UserName = "testname",
            };

            var userServiceMock = new UserServiceFixture()
                .WithSucceededFindByEmailAsync(loginCommand.Email)
                .WithSucceededGetRolesAsync(user)
                .GetMock();

            // Problematic MOCK
            var result = new Mock<ISignInServiceResult>()
                .SetupProperty(l => l.Succeeded, true);
            var signInServiceMock = new Mock<ISignInService>();
            signInServiceMock.Setup(l => l.CheckPasswordSignInAsync(user, loginCommand.Password))
                .Returns(Task.FromResult(result.Object));

            var jwtGeneratorServiceMock = new JwtGeneratorServiceFixture()
                .WithSucceededGeneration(loginCommand.Email, new string[] { "User" })
                .GetMock();

            // Here the result is what i expect
            //var result1 = await signInServiceMock.Object.CheckPasswordSignInAsync(user, loginCommand.Password);

            // Act
            var sut = new LoginHandler.Handler(
                    userServiceMock.Object,
                    signInServiceMock.Object,
                    jwtGeneratorServiceMock.Object
                );

            var loginResponse = await sut.Handle(loginCommand, new CancellationToken());

            // Assert
            loginResponse.Should().NotBeNull();
            loginResponse.Success.Should().BeTrue();
            loginResponse.Token.Should().NotBeEmpty();
            loginResponse.RefreshToken.Should().NotBeEmpty();

The only problem is that signInServiceMock returns null when the method is called on my handler. If I call it directly on my test i recieve the expected result. But when its called on my handler it always returns null.
I have checked the setup method and the params needed, all seems correct. Any idea? Thanks
The handler is this:

public class Handler : IRequestHandler<LoginCommand, LoginResponse>
{
    private readonly IUserService _userService;
    private readonly ISignInService _signInService;
    private readonly IJwtGeneratorService _jwtGeneratorService;

    public Handler(IUserService userService, ISignInService signInService, IJwtGeneratorService jwtGeneratorService)
    {
        _userService = userService;
        _signInService = signInService;
        _jwtGeneratorService = jwtGeneratorService;
    }

    public async Task<LoginResponse> Handle(LoginCommand command, CancellationToken _cancellationToken)
    {
        var user = await _userService.FindByEmailAsync(command.Email);

        if (user is null) throw new InvalidLoginCredentialsException();

        ISignInServiceResult checkedPassword 
            = await _signInService.CheckPasswordSignInAsync(user, command.Password);

        if (!checkedPassword.Succeeded) throw new InvalidLoginCredentialsException();

        var roles = await _userService.GetRolesAsync(user);

        if (roles is null)
            throw new UnableToGetRolesException();

        ITokenData? token = _jwtGeneratorService.Generate(user.Email, roles);

        if (token is null)
            throw new LoginTokenGenerationException();

        return new LoginResponse
        {
            Success = true,
            Token = token.Token,
            RefreshToken = token.RefreshToken
        };
    }
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

The problem is that your mock setup is not correctly aligned with how your Handler internally uses it.

In your setup you have this:

var user = new User
{
    Email = loginCommand.Email,
    UserName = "testname",
};

signInServiceMock.Setup(l => l.CheckPasswordSignInAsync(user, loginCommand.Password))
                 .Returns(Task.FromResult(result.Object));

That instructs the mock to return the desired result only upon receiving this exact user instance, while internally in your Handler you’re creating another User instance and passing it to the mocked method as follows:

// new User is being created:
var user = await _userService.FindByEmailAsync(command.Email);

// No longer matches your setup:
await _signInService.CheckPasswordSignInAsync(user, command.Password);

Perhaps you meant this, instead:

signInServiceMock.Setup(l => l.CheckPasswordSignInAsync(It.IsAny<User>(), loginCommand.Password))

Update:

Actually, the real problem probably lies in a missing setup of your UserService mock.

Although you’re calling .WithSucceededGetRolesAsync(user), I believe it doesn’t affect the eventual call to FindByEmailAsync(user).

All in all, you have to make sure the call to FindByEmailAsync(user) would indeed return the same user instance in your setup.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading