Reputation: 6531
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" });
}
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
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