Friday, 25 January 2019

Shared handler or DbContext in xUnit Moq testing with asp.net core

If you have multiple repository or handler being injected through controller and you want to test it with better readability In xUnit then we think about uses of shared resource that could be anything.
In most of the case we generally reuse DbContext or Repository/Provider/Handler. IClassFixture will help you to get thing done.

I preferred Collection, CollectionDefinition, given code snippet will work with you if you are implementing moq testing with ApiController.

FixtureCollection.cs
namespace xUnitTest.Helper
{
    public class MoqSerivceFixture : IDisposable
    {
        public Lazy<Mock<IUserService>> UserService;
        public MoqSerivceFixture()
        {
            UserService = new Lazy<Mock<IUserService>>();
        }
        public void Dispose()
        {
            // Some cleanup
        }
    }
 
    public class MoqRepositoryFixture : IDisposable
    {
        public DefaultContext DefaultContext;
        public MoqRepositoryFixture()
        {
            DefaultContext = new DefaultContext(new DbContextOptionsBuilder<DefaultContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString()) //Use in memory DbCOntext provided by dotnet core.
            .UseLazyLoadingProxies() // Need to install Nuget Microsoft.EntityFrameworkCore.Proxies
 
        }
        public void Dispose()
        {
            // Some cleanup
        }
    }
 
    [CollectionDefinition("FixtureCollection")]
    public class FixtureCollection<T> :
    ICollectionFixture<MoqSerivceFixture>,
    ICollectionFixture<MoqRepositoryFixture>
    {
        //Nothing needed here
    }
}

UserControllerTest.cs
namespace xUnitTest
{
    [Collection("FixtureCollection")]
    public class UserControllerTest
    {
        #region Type 1, if only service need to inject
        MoqSerivceFixture _moqSerivceFixture;
        public UserControllerTest(MoqSerivceFixture moqSerivceFixture)
        {
            _moqSerivceFixture = moqSerivceFixture;
        }
 
        #endregion

        #region Type 2, if both service & repository need to inject
        //MoqSerivceFixture _moqSerivceFixture;
        //MoqRepositoryFixture _moqRepositoryFixture;
        //public UserControllerTest(MoqSerivceFixture moqSerivceFixture, MoqRepositoryFixture moqRepositoryFixture)
        //{
        //    _moqSerivceFixture = moqSerivceFixture;
        //    _moqRepositoryFixture = moqRepositoryFixture;
        //}
        #endregion

        [Fact]
        public void GetInfoTest()
        {
            //Arrange
            UserModel responseData = new UserModel
            {
                Id = 1,
                Name = "Raj",
            };
 
            UserModel reponse = new UserModel();
            reponse = responseData;
 
            // Act
            var mockUserService = _moqSerivceFixture.UserService.Value; // getting moq value from lazy loading
            mockUserService.Setup(m => m.GetInfo(It.IsAny<long>()).Returns(reponse).Verifiable();
            var controller = new UserController(mockUserService.Object);
            var actionResult = controller.GetInfo(1);
            var result = Assert.IsType<OkObjectResult>(actionResult);
 
            // Assert                        
            Assert.NotNull(result);
            var expectedResponsedata = result.Value;
            Assert.Equal(responseData.Id, expectedResponsedata.Id);
            Assert.Equal(responseData.Name, expectedResponsedata.Name);
        }
    }
}