【问题标题】:Moq - Null reference exception when trying to test ActionResultMoq - 尝试测试 ActionResult 时出现空引用异常
【发布时间】:2014-12-18 23:46:37
【问题描述】:

我正在尝试使用 Moq 学习单元测试,但我一直遇到同样的问题。我正在为我的控制器 ActionResults 编写单元测试,我在创建控制器实例并测试它是否工作时没有问题。但是我有一个 ActionResult,它给了我一个空引用异常,因为我在调用控制器之前设置测试时遗漏了一些东西。

     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);  
        }

在我的测试中,我创建了一个新的控制器实例、模型、httppostedfilebase 的模拟,并尝试设置图像存储库 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" });
        }

截图中显示的personImagePath为空。因为我没有从我的测试中传递一个参数,所以我不知道如何让它包含一个值。我对在单元测试中如何解决这个问题感到有点困惑。任何帮助都会很棒。

【问题讨论】:

  • 在我看来 _imageRepository.SaveImage() 是罪魁祸首。您设置它,但从不指定 .Returns().Contains() 测试需要。Moq 可能返回 null 是缺少指定值。

标签: c# unit-testing model-view-controller moq


【解决方案1】:

您正在使用IImageRepository 的两个不同实例。您需要对注入到您正在测试的对象 (PersonController - IImageRepository) 的相同对象进行 Setup 调用。

要修复它,请更改

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

到(通知Returns

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

【讨论】:

  • 触摸,甚至没有看到。好决定。但是您是否还需要定义返回值,或者 Moq 是否提供 String.Emtpy?
  • @jimmy_keen 我会考虑你的建议。我对这个有点新手。
  • @jimmy_keen 我必须设置 RetrieveImageFilePath 而不是 SaveImage,但我想在我的文本中声明一个值之前,我对设置过程有更多的了解。谢谢!
猜你喜欢
  • 1970-01-01
  • 2014-07-11
  • 2011-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
相关资源
最近更新 更多