im unit testing my home controller. This test worked fine until I added a new feature which saves images.
The method that’s causing the issue is this below.
public static void SaveStarCarCAPImage(int capID)
{
byte[] capBinary = Motorpoint2011Data.RetrieveCapImageData(capID);
if (capBinary != null)
{
MemoryStream ioStream = new MemoryStream();
ioStream = new MemoryStream(capBinary);
// save the memory stream as an image
// Read in the data but do not close, before using the stream.
using (Stream originalBinaryDataStream = ioStream)
{
var path = HttpContext.Current.Server.MapPath("/StarVehiclesImages");
path = System.IO.Path.Combine(path, capID + ".jpg");
Image image = Image.FromStream(originalBinaryDataStream);
Image resize = image.GetThumbnailImage(500, 375, null, new IntPtr());
resize.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
As the call is coming from a unit test, HttpContext.Current is null and throws an exception. After reading about Moq and some of the tutorials about using Moq with sessions, im sure it can be done.
so far this the unit test code have come up with, but the issue is HTTPContext.Current is always null, and still throws the exception.
protected ControllerContext CreateStubControllerContext(Controller controller)
{
var httpContextStub = new Mock<HttpContextBase>
{
DefaultValue = DefaultValue.Mock
};
return new ControllerContext(httpContextStub.Object, new RouteData(), controller);
}
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
controller.SetFakeControllerContext();
var context = controller.HttpContext;
Mock.Get(context).Setup(s => s.Server.MapPath("/StarVehiclesImages")).Returns("My Path");
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
HomePageModel model = (HomePageModel)result.Model;
Assert.AreEqual("Welcome to ASP.NET MVC!", model.Message);
Assert.AreEqual(typeof(List<Vehicle>), model.VehicleMakes.GetType());
Assert.IsTrue(model.VehicleMakes.Exists(x => x.Make.Trim().Equals("Ford", StringComparison.OrdinalIgnoreCase)));
}
HttpContext.Current is something that you should absolutely never use if you ever expect your code to be unit tested. It is a static method which simply returns null if there is no web context which is the case of a unit test and cannot be mocked. So one way to refactor your code would be the following:
public static void SaveStarCarCAPImage(int capID, string path)
{
byte[] capBinary = Motorpoint2011Data.RetrieveCapImageData(capID, path);
if (capBinary != null)
{
MemoryStream ioStream = new MemoryStream();
ioStream = new MemoryStream(capBinary);
// save the memory stream as an image
// Read in the data but do not close, before using the stream.
using (Stream originalBinaryDataStream = ioStream)
{
path = System.IO.Path.Combine(path, capID + ".jpg");
Image image = Image.FromStream(originalBinaryDataStream);
Image resize = image.GetThumbnailImage(500, 375, null, new IntPtr());
resize.Save(path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
You see, now this method no longer depends on any web context and can be tested in isolation. It will be the responsibility of the caller to pass the correct path.
I agree with the Darin´s answer but if you really need to moq the Server.MapPath function you could do something like this
//...
var serverMock = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
serverMock.Setup(i => i.MapPath(It.IsAny<String>()))
.Returns((String a) => a.Replace("~/", #"C:\testserverdir\").Replace("/",#"\"));
//...
Performing this, the mock will simply replace the ~/ with the c:\testserverdir\ function
Hope it helps!
It is sometimes handy to just mock the call to server.MapPath.
This solution works for me using moq.
I only mock the base path to the application.
_contextMock = new Mock<HttpContextBase>();
_contextMock.Setup(x => x.Server.MapPath("~")).Returns(#"c:\yourPath\App");
_controller = new YourController();
_controller.ControllerContext = new ControllerContext(_contextMock.Object, new RouteData(), _controller);
In your controller you can now user Server.MapPath("~").
Below works for me.
string pathToTestScripts = #"..\..\..\RelatavePathToTestScripts\";
string testScriptsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, pathToTestScripts);
var server = new Mock<HttpServerUtilityBase>(); // Need to mock Server.MapPath() and give location of random.ps1
server.Setup(x => x.MapPath(PowershellScripts.RANDOM_PATH)).Returns(testScriptsFolder + "random.ps1");
var request = new Mock<HttpRequestBase>(); // To mock a query param of s=1 (which will make random.ps1 run for 1 second)
request.Setup(x => x.QueryString).Returns(new System.Collections.Specialized.NameValueCollection { { "s", "1" } });
var httpContext = new Mock<HttpContextBase>();
httpContext.Setup(x => x.Server).Returns(server.Object);
httpContext.Setup(x => x.Request).Returns(request.Object);
YourController controller = new YourController();
controller.ControllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
Related
I'm working on CRUD unit test cases with having configuration .Net 5, Automapper, xUnit etc.
The issue:
So right now I'm having issue specifically in post call and when I uses Dto.
I tried lots of ways to resole it and I was also able to resolve it if I don't use Dto in post call as input parameter and just use Entity it self. (But I don't want to expose entity so I want to make it working with Dto only)
Below is test which is not working and it's controller side implementation.
Failing Test case:
[Fact]
public void PostTest()
{
try
{
//Arrange
var surveyRequest = new SurveyRequest()
{
Id = 0,
Name = "Survey Request 1",
CreateDate = DateTime.Now,
CreatedBy = 1
};
var addedSurveyRequest = new SurveyRequest()
{
Id = 1,
Name = "Survey Request 1",
CreateDate = DateTime.Now,
CreatedBy = 1
};
//setup mock
Mock<IRepositoryWrapper> mockRepo = new Mock<IRepositoryWrapper>();
mockRepo.Setup(m => m.SurveyRequest.Add(addedSurveyRequest)).Returns(new Response<SurveyRequest>(true, addedSurveyRequest));
//auto mapper
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfile());
});
var mapper = mockMapper.CreateMapper();
SurveyRequestController controller = new SurveyRequestController(repositories: mockRepo.Object, mapper: mapper);
//Act
var model = mapper.Map<SurveyRequest, SurveyRequestDto>(source: addedSurveyRequest);
var result = controller.Post(model); // The issue with this post call here is that response remains null on repository level.
//Assert
var okResult = result as OkObjectResult;
Assert.NotNull(okResult);
//we will make sure that returned object is dto and not actual entity
var response = okResult.Value as SurveyRequestDtoWithId;
Assert.NotNull(response);
Assert.Equal(expected: response.Name, actual: model.Name);
}
catch (Exception ex)
{
//Assert
Assert.False(true, ex.Message);
}
}
Controller side post call:
[HttpPost("Insert")]
public IActionResult Post([FromBody] SurveyRequestDto model)
{
try
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
//If I remove this mapping from here, test case will work. (see next working test case)
var entity = _mapper.Map<SurveyRequestDto, SurveyRequest>(source: model);
entity.CreateDate = System.DateTime.Now;
entity.CreatedBy = 1;
var response = _repositories.SurveyRequest.Add(entity: entity); //Response remains null here
_repositories.Save();
if (response.IsSuccess == true)
return new OkObjectResult(_mapper.Map<SurveyRequest, SurveyRequestDtoWithId>(source: response.Data));
else
return new ObjectResult(response.ErrorMessage) { StatusCode = 500 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
Working Test case:
[Fact]
public void PostTest2()
{
try
{
//Arrange
var surveyRequest = new SurveyRequest()
{
Id = 0,
Name = "Survey Request 1",
CreateDate = DateTime.Now,
CreatedBy = 1
};
var addedSurveyRequest = new SurveyRequest()
{
Id = 1,
Name = "Survey Request 1",
CreateDate = DateTime.Now,
CreatedBy = 1
};
//setup mock
Mock<IRepositoryWrapper> mockRepo = new Mock<IRepositoryWrapper>();
mockRepo.Setup(m => m.SurveyRequest.Add(surveyRequest)).Returns(value: new Response<SurveyRequest>(true, addedSurveyRequest));
//auto mapper
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfile());
});
var mapper = mockMapper.CreateMapper();
//setup controlller
SurveyRequestController controller = new SurveyRequestController(repositories: mockRepo.Object, mapper: mapper);
//Act
//var model = mapper.Map<SurveyRequest, SurveyRequestDto>(source: surveyRequest);
var result = controller.Post2(entity: surveyRequest);
//Assert
var okResult = result as OkObjectResult;
Assert.NotNull(okResult);
///we will make sure that returned object is dto and not actual entity
var response = okResult.Value as SurveyRequestDtoWithId;
Assert.NotNull(response);
Assert.Equal(expected: response.Id, actual: addedSurveyRequest.Id);
Assert.Equal(expected: response.Name, actual: addedSurveyRequest.Name);
}
catch (Exception ex)
{
//Assert
Assert.False(true, ex.Message);
}
}
Controller side Post call for working test case:
[HttpPost("Insert")]
public IActionResult Post2([FromBody] SurveyRequest entity)
{
try
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
//var entity = _mapper.Map<SurveyRequestDto, SurveyRequest>(source: model);
//entity.CreateDate = System.DateTime.Now;
//entity.CreatedBy = 1;
var response = _repositories.SurveyRequest.Add(entity: entity); //This returns proper response with saved data and ID
_repositories.Save();
if (response.IsSuccess == true)
return new OkObjectResult(_mapper.Map<SurveyRequest, SurveyRequestDtoWithId>(source: response.Data));
else
return new ObjectResult(response.ErrorMessage) { StatusCode = 500 };
}
catch (Exception ex)
{
return new ObjectResult(ex.Message) { StatusCode = 500 };
}
}
I'm not sure whether my test case setup for mapper is wrong or any other issue. I also tried lots of ways but no luck so far. So posting here if someone can look and help, will be much appreciated.
If you are using IMapper then you can do something like this:
var mapperMock = new Mock<IMapper>();
mapperMock
.Setup(mapper => mapper.Map<SurveyRequestDto, SurveyRequest>(It.IsAny< SurveyRequestDto>()))
.Returns(surveyRequest);
This solution does not utilize the AutoMapperProfile, but because you have only a single mapping that's why I think it not really a problem.
If you want to call Verify on the mapperMock then I would suggest to extract the Map selector delegate like this:
private static Expression<Func<IMapper, SurveyRequestDto>> MapServiceModelFromRequestModelIsAny =>
mapper => mapper.Map<SurveyRequestDto, SurveyRequest>(It.IsAny< SurveyRequestDto>());
Usage
//Arrange
mapperMock
.Setup(MapServiceModelFromRequestModelIsAny)
.Returns(surveyRequest);
...
//Assert
mapperMock
.Verify(MapServiceModelFromRequestModelIsAny, Times.Once);
UPDATE #1
It might also make sense to be as explicit as possible when you make assertion. If you want to you can do deep equality check to make sure that controller's parameter is not amended before the Map call:
private static Expression<Func<IMapper, SurveyRequestDto>> MapServiceModelFromRequestModel(SurveyRequestDto input) =>
mapper => mapper.Map<SurveyRequestDto, SurveyRequest>(It.Is< SurveyRequestDto>(dto => dto.deepEquals(input)));
//Assert
mapperMock
.Verify(MapServiceModelFromRequestModel(model), Times.Once);
This assumes that deepEquals is available as an extension method.
UPDATE #2
As it turned out the mock repository's Setup code also had some problem. Namely it used the surveyRequest rather than a It.IsAny<SurveyRequest>().
Because surveyRequest was specified as the expected parameter that's why the setupped code path is never called but returned with null.
After changed it to It.IsAny then the whole test started to work :D
repoMock
.Setup(repo => repo.SurveyRequest.Add(It.IsAny<SurveyRequest>()))
.Returns(new Response<SurveyRequest>(true, addedSurveyRequest))
I have a method in WebApi controller that I want to write unit tests for. This is how my controller method looks:
Controller.cs
public async Task<FileUploadDto> UploadGoalDocument(Guid id)
{
var file = this.Request?.Form?.Files.FirstOrDefault();
FileUploadDto result = null;
if (file == null)
{
return this.CreateResponse(result);
}
//logic to store file in db
return this.CreateResponse(new FileUploadDto() { Id = document.Id, Name = document.Name, Uri = document.Uri});
}
How can I mock the request object in unit testing? I tried following but ran into problems with IFormFileCollection. The following line throws error:
system.argumentexception interface not found
cc.Setup(x => x.HttpContext.Request.Form.Files).Returns(col.Object);
ControllerTest.cs
public async Task Upload_document_should_upload_document_and_return_dto()
{
var fileDto = new FileUploadDto { Id = Guid.NewGuid(), Name = "dummy.txt" };
var fileMock = new Mock<IFormFile>();
//Setup mock file using a memory stream
using (var ms = new MemoryStream())
{
using (var writer = new StreamWriter("dummy.txt"))
{
writer.WriteLine("Hello World from a Fake File");
writer.Flush();
ms.Position = 0;
fileMock.Setup(m => m.OpenReadStream()).Returns(ms);
var file = fileMock.Object;
this.goalService.Setup(m => m.UploadDocument(Guid.NewGuid(), file, ""))
.ReturnsAsync(new Services.DTO.FileUploadDto { Id = fileDto.Id, Name = fileDto.Name });
var cc = new Mock<ControllerContext>();
var col = new Mock<IFormFileCollection>();
col.Setup(x=> x.GetFile("dummy.txt")).Returns(file);
cc.Setup(x => x.HttpContext.Request.Form.Files).Returns(col.Object);
this.controller.ControllerContext = cc.Object;
var result = await this.controller.UploadGoalDocument(Guid.NewGuid());
//Asserts removed for simplicity
}
}
}
Detailed stack trace:
System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle)
at System.RuntimeType.GetInterfaceMap(Type ifaceType)
at Moq.Extensions.IsGetObjectDataVirtual(Type typeToMock)
at Moq.Extensions.IsSerializableMockable(Type typeToMock)
at Moq.SerializableTypesValueProvider.ProvideDefault(MethodInfo member)
at Moq.Mock.GetInitialValue(IDefaultValueProvider valueProvider, Stack`1 mockedTypesStack, PropertyInfo property)
at Moq.Mock.SetupAllProperties(Mock mock, Stack`1 mockedTypesStack)
at Moq.Mock.<>c__DisplayClass72_0.<SetupAllProperties>b__0()
at Moq.PexProtector.Invoke(Action action)
at Moq.Mock.SetupAllProperties(Mock mock)
at Moq.QueryableMockExtensions.FluentMock[T,TResult](Mock`1 mock, Expression`1 setup)
at lambda_method(Closure )
at Moq.Mock.GetInterceptor(Expression fluentExpression, Mock mock)
at Moq.Mock.<>c__DisplayClass66_0`2.<SetupGet>b__0()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.SetupGet[T,TProperty](Mock`1 mock, Expression`1 expression, Condition condition)
at Moq.Mock.<>c__DisplayClass65_0`2.<Setup>b__0()
at Moq.PexProtector.Invoke[T](Func`1 function)
at Moq.Mock.Setup[T,TResult](Mock`1 mock, Expression`1 expression, Condition condition)
at Moq.Mock`1.Setup[TResult](Expression`1 expression)
I am thinking I have not constructed the test properly, but a keen eye can point me in the right direction.
For anyone facing similar problem, here's what I did to get it working -
ControllerTest.cs
[TestMethod]
public async Task Upload_document_should_upload_document_and_return_dto()
{
var goalId = Guid.NewGuid();
var file = new Services.DTO.FileUploadDto { Id = goalId, Name = "dummy.txt", Uri = "path/to/file" };
this.goalService.Setup(m => m.UploadDocument(It.IsAny<Guid>(), It.IsAny<IFormFile>(), It.IsAny<string>())).ReturnsAsync(file);
//**This is the interesting bit**
this.controller.ControllerContext = this.RequestWithFile();
var result = await controller.UploadGoalDocument(goalId);
Assert.IsNotNull(result);
Assert.AreEqual(file.Id, result.Data.Id);
Assert.AreEqual(file.Name, result.Data.Name);
Assert.AreEqual(file.Uri, result.Data.Uri);
}
//Add the file in the underlying request object.
private ControllerContext RequestWithFile()
{
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers.Add("Content-Type", "multipart/form-data");
var file = new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("This is a dummy file")), 0, 0, "Data", "dummy.txt");
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>(), new FormFileCollection { file });
var actx = new ActionContext(httpContext, new RouteData(), new ControllerActionDescriptor());
return new ControllerContext(actx);
}
I am developing an ASP.NET MVC project. In my project I am doing unit testing. I am using Moq to mock my business logics. But I am having a problem with Moq. Especially with mock.Verify method.
This is the action I am testing
[HttpPost]
public ActionResult Edit(CreateRegionVM model)
{
if(ModelState.IsValid)
{
Region region = new Region
{
Id = model.Id,
Name = model.Name,
MmName = model.MmName,
Description = model.Description,
MmDescription = model.MmDescription,
GeoLocation = model.GeoLocation,
ImagePath = model.ImagePath
};
String imagePath = String.Empty;
if(model.ImageFile!=null && model.ImageFile.ContentLength>0)
{
imagePath = fileHelper.UploadFile(model.ImageFile, AppConfig.RegionImageDir,null);
if(String.IsNullOrEmpty(imagePath))
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
else
{
//create thumb & delete old images - check the image operations
fileHelper.CreateThumb(imagePath, AppConfig.RegionImageDir, AppConfig.RegionMediumThumbWidth, AppConfig.RegionMediumThumbHeight, AppConfig.MediumThumbSuffix);
fileHelper.CreateThumb(imagePath, AppConfig.RegionImageDir, AppConfig.RegionSmallThumbWidth, AppConfig.RegionSmallThumbHeight, AppConfig.SmallThumbSuffix);
fileHelper.DeleteFile(model.ImagePath);
fileHelper.DeleteFile(fileHelper.GetImagePath(model.ImagePath, AppConfig.MediumThumbSuffix));
fileHelper.DeleteFile(fileHelper.GetImagePath(model.ImagePath, AppConfig.SmallThumbSuffix));
model.ImagePath = imagePath;
}
}
try
{
regionRepo.Update(region);
TempData["message"] = "Region successfully edited";
TempData["class"] = AppConfig.FlashSuccessClass;
return RedirectToAction("Edit", new { id = model.Id });
}
catch
{
return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
}
}
return View("Create",model);
}
This is my test function
[TestMethod]
public void Edited_And_Redirected()
{
var postFile = new Mock<HttpPostedFileBase>();
postFile.Setup(m => m.ContentLength).Returns(1);
CreateRegionVM model = new CreateRegionVM
{
Id = 1,
Name = "test",
ImageFile = postFile.Object
};
Mock<IRegionRepo> regionMock = new Mock<IRegionRepo>();
regionMock.Setup(m => m.Update(new Region())).Verifiable();
Mock<IFileHelper> fileMock = new Mock<IFileHelper>();
fileMock.Setup(m => m.UploadFile(model.ImageFile, It.IsAny<String>(), null)).Returns("upload_file_path");
RegionController controller = new RegionController(regionMock.Object, fileMock.Object, 0);
var unknownView = controller.Edit(model);
regionMock.Verify();
Assert.IsInstanceOfType(unknownView, typeof(RedirectToRouteResult), "Not redirected");
}
As you can see my test method, I am using verify to make sure regionRepo.Update method is called. But it is giving me this error when I run the test.
Moq.MockVerification Exception: The following setups were not matched:
IRegionRepo m=>m=>Update()
Why is this error thrown? How does the verify method of moq work?
Take a look at this line:
regionMock.Setup(m => m.Update(new Region())).Verifiable();
It's going to compare the input to new Region(), but most likely whatever you're passing in is not going to be referentially equal to that.
If the Region doesn't matter, try
regionMock.Setup(m => m.Update(It.IsAny<Region>())).Verifiable();
Here is the Test method Creating a mock for request and context
have added the querystring to the context and while debugging the TestMethod could able to see the values of the querystring collection
[TestMethod]
public void Save_Tester()
{
//Arrange
HomeController controller = new HomeController();
string querystring = "?key1=value1&key2=value2&key3=value3&key4=value4";
Mock<HttpRequestBase> mock_request = MockHelpers.CreateMockRequest(querystring);
Mock<HttpContextBase> mock_context = new Mock<HttpContextBase>();
//Request
NameValueCollection myValues = new NameValueCollection();
FormCollection formcollection = new FormCollection(myValues);
mock_request.SetupGet(mr => mr.Params).Returns(myValues);
mock_request.SetupGet(mr => mr.Form).Returns(myValues);
mock_request.SetupGet(mr => mr.QueryString).Returns(HttpUtility.ParseQueryString(querystring));
//Context
mock_context.Setup(c => c.Request).Returns(mock_request.Object);
controller.ValueProvider = formcollection.ToValueProvider();
// Act
Assert.IsNotNull(controller); //Guard
var result_query = controller.Save() as ViewResult;
// Assert
}
In the save method using QueryStringValueProvider to get the Values but has no namevaluecollection
QueryStringValueProvider takes the ControllerContext.HttpContext.Request.QueryString that to avail in debugging
[HttpPost]
public ActionResult Save()
{
try
{
IValueProvider provider = new QueryStringValueProvider(this.ControllerContext);
//provider has no namevaluecollection values
}
catch
{
throw;
}
}
Solution
This solved it I should have taken some time to analyse before putting a question
Uri uri = new Uri("http://localhost?key1=value1&key2=value2&key3=value3&&key4=value4");
HttpRequest httpRequest = new HttpRequest(string.Empty, uri.ToString(),
uri.Query.TrimStart('?'));
HttpContext httpContext = new HttpContext(httpRequest, new HttpResponse(new StringWriter()));
HttpSessionStateContainer sessionContainer = new HttpSessionStateContainer("id",
new SessionStateItemCollection(),
new HttpStaticObjectsCollection(),
10, true, HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
SessionStateUtility.AddHttpSessionStateToContext(
httpContext, sessionContainer);
HttpContext.Current = httpContext;
I have the following method:
public void SetHttpStatusCode(HttpStatusCode httpStatusCode)
{
Response.StatusCode = (int)httpStatusCode;
}
And the following test:
[TestMethod]
public void SetHttpStatusCode_SetsCorrectStatusCode()
{
//Arrange
//Any url will suffice
var mockHttpContext = TestHelpers.MakeHttpContext("");
mockHttpContext.SetupSet(x => x.Response.StatusCode = It.IsAny<int>());
//creates an instance of an asp.net mvc controller
var controller = new AppController()
{
ControllerContext = new ControllerContext() {
HttpContext = mockHttpContext.Object }
};
// Act
controller.SetHttpStatusCode(HttpStatusCode.OK);
//Assert
mockHttpContext.VerifySet(x => x.Response.StatusCode = It.IsAny<int>());
}
Also, Here is MakeHttpContext
public static Mock<HttpContextBase> MakeHttpContext(string url)
{
var mockHttpContext = new Mock<HttpContextBase>();
var mockRequest = new Mock<HttpRequestBase>();
var mockResponse = new Mock<HttpResponseBase>();
var mockSession = new Mock<HttpSessionStateBase>();
//request
mockRequest.Setup(x => x.AppRelativeCurrentExecutionFilePath).Returns(url);
mockHttpContext.Setup(x => x.Request).Returns(mockRequest.Object);
//response
mockResponse.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);
mockHttpContext.Setup(x => x.Response).Returns(mockResponse.Object);
//session
mockHttpContext.Setup(x => x.Session).Returns(mockSession.Object);
return mockHttpContext;
}
When I run the test, I get the following exception:
Test method PA.Tests.Controllers.AppControllerTest.SetHttpStatusCode_SetsCorrectStatusCode
threw exception:
Moq.MockException:
Expected invocation on the mock at least once,
but was never performed: x => x.StatusCode = It.IsAny<Int32>()
Configured setups:
x => x.StatusCode = It.IsAny<Int32>(), Times.Never
No invocations performed.
How does Moq expect/require invocations to be called? I've debugged the SetHTTPStatusCode method, the response object is indeed a mocked object, however Moq insists that there was no invocation. Am I missing something?
Thanks!
You haven't shown what your TestHelpers.MakeHttpContext method does so it's a bit difficult to understand what's going on.
Try like this:
// Arrange
var mockHttpContext = new Mock<HttpContextBase>();
var response = new Mock<HttpResponseBase>();
mockHttpContext.SetupGet(x => x.Response).Returns(response.Object);
//creates an instance of an asp.net mvc controller
var controller = new AppController()
{
ControllerContext = new ControllerContext()
{
HttpContext = mockHttpContext.Object
}
};
// Act
controller.SetHttpStatusCode(HttpStatusCode.OK);
//Assert
response.VerifySet(x => x.StatusCode = (int)HttpStatusCode.OK);