nick gowdy
nick gowdy

Reputation: 6531

Moq - Null reference exception when trying to test ActionResult

I'm trying to learn unit testing with Moq but I keep running into the same issue. I am writing unit tests for my controller ActionResults and I don't have a problem with creating an instance of my controller and testing that it works. But I have an ActionResult that gives me a null reference exception because I am missing something with setting up my test before calling the controller.

     private PersonController _controller;
     private Mock<ICoreRepository> _repoCore;
     private Mock<IImageRepository> _repoImage;

     [TestInitialize]
     public void Setup()
     {
         _repoCore = new Mock<ICoreRepository>();
         _repoImage = new Mock<IImageRepository>();

         _controller = new PersonController(_repoImage.Object)
         {
             CrmCoreRepository = _repoCore.Object,
             //ImageRepository = _repoImage.Object
         };
      }

        [TestMethod]
        public void UploadImage_NotNull_personImage_Test()
        {

            var controller = new PersonController(_repoImage.Object);
            var model = new GlobalEntityModel
            {
                PersonModel= new PersonModel()
            };

            controller.CrmCoreRepository = _repoCore.Object;
             var uploadedFile = new Mock<HttpPostedFileBase>();

            uploadedFile
                .Setup(f => f.ContentLength)
                .Returns(10);

            uploadedFile
                .Setup(f => f.FileName)
                .Returns("testimage.jpg");

            var imageRepository = new Mock<IImageRepository>();
            imageRepository.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(), It.IsAny<ImagePaths>()));

            var res = controller.AddOrUpdatePersonDetail(model, uploadedFile.Object);

            Assert.IsNotNull(res);  
        }

In my test I create a new controller instance, model, a mock of httppostedfilebase and I try to setup the image repository saveImage.

[HttpPost]
        public ActionResult AddOrUpdatePersonDetail(GlobalEntityModel model, HttpPostedFileBase personImage)
        {
            var uploadedImage = string.Empty;
            var personImagePath = _imageRepository.RetrieveImageFilePath(ImagePaths.PersonImageFilePath);

            if (personImage != null)
            {
                uploadedImage = _imageRepository.SaveImage(personImage, ImagePaths.PersonImageFilePath);
            }

            var personModel = model.PersonModel;
            var personDto = Mapper.MapTo<PersonDto>(personModel);

            //Update Person
            personDto.CreatedBy = "Admin";
            personDto.UpdatedBy = "Admin";
            personDto.UpdatedOn = DateTime.Now;

            if (uploadedImage != string.Empty)
            {
                personDto.PersonImageRef = uploadedImage;

                if (personDto.PersonImageRef.Contains(personImagePath))
                {
                    personDto.PersonImageRef = personDto.PersonImageRef.Replace(personImagePath, string.Empty);
                }
                if (personDto.PersonImageRef.Contains("~/Content"))
                {
                    personDto.PersonImageRef = string.Empty;
                }
            }

            if (personDto.Id == 0)
            {
                personDto.GlobalEntityGUID = model.GlobalEntityGUID;

                personDto = CrmCoreRepository.AddPerson(personDto, null, null, null);

                if (personDto != null)
                {
                    personModel.GlobalEntityGUID = personDto.GlobalEntityGUID;

                    var personDetailModel = model.PersonDetailModel;
                    personDetailModel.PersonId = personDto.Id;

                    var personDetailDto = Mapper.MapTo<PersonDetailDto>(personDetailModel);
                    personDetailDto.CreatedBy = "Admin";
                    personDetailDto.UpdatedBy = "Admin";

                   personDetailDto = personDetailModel.Id == 0 ? CrmCoreRepository.AddPersonDetail(personDetailDto) : CrmCoreRepository.UpdatePersonDetail(personDetailDto);                
                }
            }
            else if (personDto.Id > 0)
            {
                personDto = CrmCoreRepository.UpdatePerson(personDto, null, null, null);

                if (personDto != null)
                {
                    personModel.GlobalEntityGUID = personDto.GlobalEntityGUID;

                    var personDetailModel = model.PersonDetailModel;
                    personDetailModel.PersonId = personDto.Id;

                    var personDetailDto = Mapper.MapTo<PersonDetailDto>(personDetailModel);
                    personDetailDto.CreatedBy = "Admin";
                    personDetailDto.UpdatedBy = "Admin";

                    personDetailDto = personDetailModel.Id == 0 ? CrmCoreRepository.AddPersonDetail(personDetailDto) : CrmCoreRepository.UpdatePersonDetail(personDetailDto);
                }
            }

            return RedirectToRoute("EditEntity", new { controller = "GlobalEntity", action = "EditEntity", entityGuid = personModel.GlobalEntityGUID, entityType = "P" });
        }

enter image description here

personImagePath as shown in the screenshot is null. Because I am not passing a parameter from my test I don't know how to make it contain a value. I am a bit confused with what to do in the unit test to fix this. Any help would be great.

Upvotes: 2

Views: 3347

Answers (1)

k.m
k.m

Reputation: 31464

You are using two different instances of IImageRepository. You need to make Setup calls on the same objects that were injected to object you are testing (PersonController - IImageRepository).

To fix it, change

var imageRepository = new Mock<IImageRepository>();
imageRepository.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(),
    It.IsAny<ImagePaths>()));

to (notice Returns)

_repoImage.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(),
    It.IsAny<ImagePaths>())).Returns("~/Content");

Upvotes: 3

Related Questions