Skip to content

C# Xunit & Moq mocking generic repository, unitOfWork repository always returns null #1323

@deva7mad

Description

@deva7mad

The problem is when I try to mock any method of the repository, for example GetFirstOne, it always return null during debugging.

C# mocking generic repository, unitOfWork and applying filter expression return exception that because repository always returns null

Method in service class that I wrote test for it:

    public bool ResetPassword(ChangePasswordDto changePasswordDto)
    {
        var userQueryCriteria = UserOfMobileQueryCriteria(changePasswordDto.MobileNumber);
        
        var user = _unitOfWork.UserRepository.GetFirstOne(userQueryCriteria);

        if (user is null)
            throw new RecordNotFoundException(_configReader.GetKey(ConfigKeys.ExceptionRecordNotFound.ToString()),
                SharedErrorCode.RecordNotFound);

        var verification = _verificationService.IsRecentlyVerified(user.Id, changePasswordDto.MobileNumber, changePasswordDto.NotificationChannelType);
        
        if (verification is {IsVerified: false})
            throw new UserNotVerifiedException(_configReader.GetKey(ConfigKeys.ExceptionUserIsNotVerified.ToString()),
                SharedErrorCode.UserNotVerified);

        var newPassword = _generalUtility.HashPassword(changePasswordDto.Password,
            _configReader.GetKey(ConfigKeys.HashSalt.ToString()));

        if (user.Password == newPassword)
            throw new AuthenticationException(
                _configReader.GetKey(ConfigKeys.ExceptionNewPasswordIsSimilarOldOne.ToString()),
                SharedErrorCode.NewPasswordLikeOldOne);

        user.Password = newPassword;
        _unitOfWork.UserRepository.Update(user);
        _unitOfWork.Save();

        return true;
    }

Implementation of UserOfMobileQueryCriteria method:

protected virtual BaseQueryCriteria<UserEntity> UserOfMobileQueryCriteria(string mobileNumber)
{
    return new BaseQueryCriteria<UserEntity>(_ => _.MobileNumber == mobileNumber);
}

Implementation of GetFirstOne method:

public override T? GetFirstOne(IQuerySpecification<T> specification)
{
  return ApplySpecification(specification).FirstOrDefault();
}

private IQueryable<T> ApplySpecification(IQuerySpecification<T> spec)
{
    return GetQuery(_dbContext.Set<T>().AsQueryable(), spec);
}

private static IQueryable<T> GetQuery(IQueryable<T> queryable, IQuerySpecification<T> specification)
{
   var query = queryable;
   query = query.Where(specification.Filter);
          
   return query;
}

Test:

[Fact]
public void ResetPasswordReturnTrue()
{
 //Arrange
  var changePasswordDto = new ChangePasswordDto()
  {
    Code = "1234",
    Password = "stringst",
    PasswordConfirmation = "stringst",
    MobileNumber = "+111111111111",
    NotificationChannelType = NotificationChannelType.SMS
   };
        
   var user = new UserEntity
   {
     Id = Guid.NewGuid().ToString(),
     MobileNumber = changePasswordDto.MobileNumber,
     Role = UserRoles.Parent,
            FirstName = "Ahmad",
            LastName = "Ke"
        };

        Expression<Func<UserEntity, bool>> e = x => x.MobileNumber == changePasswordDto.MobileNumber;

        var userQueryBuilderMock = new Mock<BaseQueryCriteria<UserEntity>>(e);
        
        _userServiceMock.Protected()
            .Setup<BaseQueryCriteria<UserEntity>>("UserOfMobileQueryCriteria", changePasswordDto.MobileNumber)
            .Returns(  userQueryBuilderMock.Object );
        
       
        _userUnitOfWorkMock.Setup(r =>
                r.UserRepository.GetFirstOne(userQueryBuilderMock.Object))
            .Returns(user);
        
        var verification = new VerificationResponseDto
        {
            Code = changePasswordDto.Code,
            Id = Guid.NewGuid().ToString(),
            Recipient = user.MobileNumber,
            IsVerified = true,
            SendDate = DateTime.Today.AddMinutes(-10),
            UserId = user.Id,
            NotificationChannelType = changePasswordDto.NotificationChannelType
        };
        
  _verificationServiceMock.Setup(v => v.IsRecentlyVerified(user.Id, user.MobileNumber,NotificationChannelType.SMS)).Returns(verification);
        
  //Act
  var passwordChanged = _passwordService.ResetPassword(changePasswordDto);
        
  //Assert
  Assert.True(passwordChanged);
}

IUserUnitOfWork & UserUnitOfWork

public interface IUserUnitOfWork : IUnitOfWork
{
   IRepository<UserEntity> UserRepository { get; }
}

public class UserUnitOfWork : IUserUnitOfWork
{
  private readonly UserDbContext _userContext;
  public IRepository<UserEntity> UserRepository { get; }

  public UserUnitOfWork(UserDbContext userContext, IRepository<UserEntity> userRepository)
 {
  _userContext = userContext;

 UserRepository = userRepository;
 }

        public void Save()
        {
            _userContext.SaveChanges();
        }

        public void Dispose()
        {
            _userContext.Dispose();
        }
    }

Result exception:

Exceptions.RecordNotFoundException

Exception of type 'Exceptions.RecordNotFoundException' was thrown.

at Application.UserService.ResetPassword(ChangePasswordDto changePasswordDto) in Application\UserPasswordService.cs:line 23
at UnitTests.User.Application.UserServiceTest.ResetPasswordReturnTrue() in User\Application\UserServiceTest.cs:line 91

Back this issue
Back this issue

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions