4

I'm writing unit test for my UserRepository class where I'm using AutoMapper ProjectTo<T> Queryable Extensions for projection. Here is how the class looks like:

public class UserRepository:IUserRepository
    {
        private readonly UserManager<UserEntity> _userManager;
        private readonly IConfigurationProvider _mappingConfiguration;

        public UserRepository(
            UserManager<UserEntity> userManager,
            IConfigurationProvider mappingConfiguration)
        {
            _userManager = userManager;
            _mappingConfiguration = mappingConfiguration;
        }

        public async Task<IEnumerable<User>> GetUsersAsync()
        {
            IQueryable<UserEntity> query = _userManager.Users;

            var size = await query.CountAsync();

            var items = await query
                .ProjectTo<User>(_mappingConfiguration)
                .ToArrayAsync();

            return items;
        }
    }

I'm using x-unit unit test project. Here is my test class,

public class UserRepositoryTests
    {
        [Fact]
        public async void GetUsers_AtleastOne_ReturnOneOrMore()
        {
            // Arrange
            var connectionStringBuilder =
                new SqliteConnectionStringBuilder { DataSource = ":memory:" };
            var connection = new SqliteConnection(connectionStringBuilder.ToString());

            var options = new DbContextOptionsBuilder<GallaContext>()
                .UseSqlite(connection)
                .Options;

            var mockHttpContextAccessor = new Mock<IHttpContextAccessor>();
            var mockUserManager = new Mock<UserManager<UserEntity>>(new Mock<IUserStore<UserEntity>>().Object,
                    new Mock<IOptions<IdentityOptions>>().Object,
                    new Mock<IPasswordHasher<UserEntity>>().Object,
                    new IUserValidator<UserEntity>[0],
                    new IPasswordValidator<UserEntity>[0],
                    new Mock<ILookupNormalizer>().Object,
                    new Mock<IdentityErrorDescriber>().Object,
                    new Mock<IServiceProvider>().Object,
                    new Mock<ILogger<UserManager<UserEntity>>>().Object);
            var mockAutoMapper = new Mock<IConfigurationProvider>();

            using (var context = new GallaContext(options, mockHttpContextAccessor.Object))
            {
                context.Database.OpenConnection();
                context.Database.EnsureCreated();

                var userRepository = new UserRepository( mockUserManager.Object, mockAutoMapper.Object);

                // Act
                var users = await userRepository.GetUsersAsync();

                // Assert
                users.Should().HaveCountGreaterOrEqualTo(1);
            }
        }
    }

I'm getting the following error when executing ProjectTo<User> in my repository class.

{System.NullReferenceException: Object reference not set to an instance of an object. at AutoMapper.QueryableExtensions.ProjectionExpression.ToCore[TResult](Object parameters, IEnumerable`1 memberPathsToExpand)

I'm new to Moq and Unit Testing, I searched a lot but couldn't find a way to Mock this. Please assist on how to properly Mock AutoMapper IConfigurationProvider along with my MappingProfile

Here is the Error Details

System.NullReferenceException
  HResult=0x80004003
  Message=Object reference not set to an instance of an object.

  Source=AutoMapper

  StackTrace:
   at AutoMapper.QueryableExtensions.ProjectionExpression.ToCore[TResult](Object parameters, IEnumerable '1 memberPathsToExpand)
   at AutoMapper.QueryableExtensions.Extensions.ProjectTo[TDestination](IQueryable source, IConfigurationProvider configuration, Expression`1[] membersToExpand)
   at Repositories.UserRepository.<GetUsersAsync>d__5.MoveNext() in ..path\:line 46
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter '1.GetResult()
   at Repositories.Test.UserRepositoryTests.<GetUsers_AtleastOne_ReturnOneOrMore>d__0.MoveNext() in ..path\Repositories.Test\UserRepositoryTests.cs:line 53

Thanks,

Abdul

7
  • This looks more like an integration test. As for the mapper. wy not use an actual instance of one. initialize an actual mapper and use that Commented Jul 4, 2019 at 14:42
  • 1
    The issue is that you don't have a Setup for the IConfigurationProvider mock, or any other mock. I would instead recommend injecting IMapper interface and mock the Map method. I will try to get back to you later tonight with a detailed answer. Commented Jul 5, 2019 at 9:49
  • 3
    Don't mock automapper, create actual instance and pass it to the repository. Commented Jul 7, 2019 at 4:13
  • 1
    Automapper is implementation details. For example I don't want to rewrite my tests if I decide to map objects manually. Commented Jul 7, 2019 at 6:46
  • 3
    You should mock only dependencies which makes your tests slow (database, file system, web services ...) or makes you tests very very very complicated to setup. Commented Jul 7, 2019 at 6:46

2 Answers 2

6

Here is how I resolved following @Fabio comments and that works.

var mockAutoMapper = new MapperConfiguration(mc => mc.AddProfile(new MappingProfile())).CreateMapper().ConfigurationProvider;
Sign up to request clarification or add additional context in comments.

Comments

0
private IMapper _mapper;

protected UserRepositoryTests()
{
    var mockAutoMapper = new MapperConfiguration(mc =>
    {
      //mc.AddProfile(new MappingProfile());
      mc.AddMaps(typeof(DefaultApplicationDTOModule).Assembly);
    }).CreateMapper().ConfigurationProvider;

    _mapper = new Mapper(mockAutoMapper);
}

To improve on your answer, scanning all your MappingProfiles

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.