Error by Mock in Unit test asp.net MVC - c#

I am doing a unit test project to test a read method in a controller. I am trying to mock the Repository but I am getting a problem.
There is an App Repository which contains all the Repositories. and another Repository for users:
var repositoriesMock = new Mock<IAppRepositories>();
var userMock = new Mock<UserRepository> ();
repositoriesMock.SetupGet(x => x.Users).Returns(
partnerMock.Object
);
userMock.SetupGet(x => x.GetUserDto(false, 1) ).Returns(
new List<GeschaeftspartnerDto> {user1, user2}.AsQueryable()
);
in the controller:
public ActionResult Read([DataSourceRequest] DataSourceRequest request)
{
var list = this.AppRepositories.Users.GetUserDto(false, 1).ToList();
}
but I am receiving an Error in uerMock.SetupGet
Expression is not a property access: x => x.GetUserDto(False, 1)
what is going on? why am I getting this error?

Try using Mock.Setup instead of Mock.SetupGet.

Related

How do you access the data returned by a controller when run in unit tests?

I have a Asp .net core 2.2 web api. I am trying to set up unit testing on a number of the controllers. I have it working to he point where it does call the controller
Controller
[HttpGet("list")]
public ActionResult Get([FromQuery] string q = null)
{
if (q != null)
return Ok(new ClientListResponse(ClientHelper.FindClientByClientIdOrClientName(_configurationDbContext.Clients, q)));
return Ok(new ClientListResponse(_configurationDbContext.Clients.ToList()));
}
Test calling it
var allClients = controller.Get();
Issue
Now when i look at it in debug everything looks fine. I can see that value contains the correct object being returned.
However when it try to access the variables they don't exist.
I am suspecting that this has something to do with the response being an ActionResult. I have tried to convert it to everything i can think of.
How do you access the data returned by a controler when run in unit tests?
Cast it to an OkObjectResult.
In ours:
var controller = SetupAdminTestsForPassword();
var result = controller.ValidateTokenForUserCreation(new ValidateUserTokenRequest() { token = "VALIDCREATEUSERTOKEN"});
var okResult = result as OkObjectResult;
// assert
Assert.IsNotNull(okResult);
Assert.IsNotNull(okResult.Value);
Assert.IsNotNull(okResult.Value as ValidateUserTokenResponse);
Assert.IsTrue((okResult.Value as ValidateUserTokenResponse).IsValid);
We're also using dotnet core 2.2 and Moq for tests.

How to Authenticate or Login from Test class into Controller

I want to test my project using visual studio unit test but it produce error of null reference of User.Identity.GetUserID() is there any way to mock it or I have to logged-in through unit test. I have searched a lot but not found the solution.
here is code to be tested
public PartialViewResult _AdmitPatient(int id)
{
if (cFunctions.AllowAccessToRecord((int)id, User.Identity.GetUserId(), "patient") == false)
{
return null;
}
Admission admission = new Admission();
admission.PatientID = id;
return PartialView(admission);
}
Here is unit test for this code
[TestMethod]
public void TestAdmitPatView()
{
var adc = new AdmissionController();
var res = adc._AdmitPatient(6);
Assert.AreEqual(adm.PatientID, res.ViewData);
}
if I have to create logged-in in unit test kindly tell me in detail how to be logged-in
HttpContext.User Property is working on the hosted application. This will be null in tests environment. Because HttpContext.User is not set by test frameworks. SO you should create a fake object via mocking frameworks like Fakeiteasy, or Moq
If you are using FakeItEasy, you can create object:
[TestMethod]
public void TestAdmitPatView()
{
var adc = new AdmissionController();
adc.ControllerContext = A.Fake<ControllerContext>();
var fakePrincipal = A.Fake<IPrincipal>();
var fakeIdentity = new GenericIdentity( "username" );
A.CallTo( () => fakePrincipal.Identity ).Returns( fakeIdentity );
A.CallTo( () => HomeController.ControllerContext.HttpContext.User ).Returns( fakePrincipal );
var res = adc._AdmitPatient(6);
Assert.AreEqual(adm.PatientID, res.ViewData);
}
if your cFunctions.AllowAccessToRecord method is calling database, you should fake it also.

How to Mock Request object in unit testing asp.net mvc application

I am working on an asp.net mvc 3.0 application. In unit testing one of the action method in my controller, I was getting an error.
How to mock: Request.Params["FieldName"]
I have included Moq framework, but was not sure how to pass value
Here is my code... Please suggest...
var request = new Mock<System.Web.HttpRequestBase>();
request
.SetupGet(x => x.Headers)
.Returns(
new System.Net.WebHeaderCollection
{
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<System.Web.HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
ValidCodeController target = new ValidCodeController();
target.ControllerContext =
new ControllerContext(context.Object, new RouteData(), target);
Params is a NameValueCollection property that can be set-up in a similar way to Headers:
var requestParams = new NameValueCollection
{
{ "FieldName", "value"}
};
request.SetupGet(x => x.Params).Returns(requestParams);
Another alternative to mocking the Context and all it's dependencies is to abstract the entire context/Params collection in a separate class, and mock that instead. In many cases this will make it easier, and avoids having to mock a complicated object graph:
Ex:
public void MainMethod()
{
var valueInQuestion = ISomeAbstraction.GetMyValue("FieldName");
}
You can now mock the GetMyValue method instead.

How to setup server variables for unit test using moq

I am using hanselman tutorial to use Moq to create unit tests for my asp.net pages.
I wrote the following code to test for ServerVariables in contextbase request class
HttpContextBase contextbase = MoqHelper.FakeHttpContext();
contextbase.Request.ServerVariables.Add("AUTH_TYPE","Forms"); <-- error here
contextbase.Request.ServerVariables.Add("LOGON_USER", "Tom");
contextbase.Request.ServerVariables.Add("REQUEST_METHOD", "GET");
But I am getting following exception. Please help.
System.NullReferenceException was unhandled by user code Message=Object reference not set to an instance of an object.
How do I create unit test to test server variables?
There are some misprint on Scott Hanselman's page (lowercase class names). So here is how code should look like (I also changed old Expect syntax with new Setup syntax):
public static class MvcMockHelpers
{
public static HttpContextBase FakeHttpContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
return context.Object;
}
}
Back to your case. You see this exception, because when fake HttpContext is created, only its direct properties Request, Response, Session and Server were setup-ed. But you are trying to access property ServerVariables of request mock. So, you need to setup some return results for this property. See example how Scott setups request url for request mock:
public static void SetupRequestUrl(this HttpRequestBase request, string url)
{
if (url == null)
throw new ArgumentNullException("url");
var mock = Mock.Get(request);
mock.Setup(req => req.QueryString)
.Returns(GetQueryStringParameters(url));
mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
.Returns(GetUrlFileName(url));
mock.Setup(req => req.PathInfo)
.Returns(string.Empty);
}
Main idea here - you cannot use directly contextBase.Request.QueryString you should setup request mock before:
mock.Setup(req => req.QueryString)
.Returns(GetQueryStringParameters(url));

How do I make a unit test to test a method that checks request headers?

I am very, very new to unit testing and am trying to write a test for a pretty simple method:
public class myClass : RequireHttpsAttribute
{
public override void OnAuthorization(AuthoizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
var header = Convert.ToBoolean(request.Headers["Special-Header-Name"]);
if (!(header || request.IsSecureConnection))
{
HandleNonHttpsRequest(filterContext);
}
}
}
This method, which inherits from the RequireHttpsAttribute, checks if a certain header is present from a page, if it's missing or false, and the page is not secure, then it will call HandleNonHttpsRequest, otherwise it does nothing.
We are using Moq and Nunit for testing. I have found some resources to help build a fakeHttpContext with Moq, but honestly I'm not sure how to use it or where to go within my unit tests to ensure that fake HttpContexts are or are not causing the HandleNonHttpsRequest method to call.
I really appreciate any guidance with this issue.
// arrange
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var headers = new NameValueCollection
{
{ "Special-Header-Name", "false" }
};
request.Setup(x => x.Headers).Returns(headers);
request.Setup(x => x.HttpMethod).Returns("GET");
request.Setup(x => x.Url).Returns(new Uri("http://www.example.com"));
request.Setup(x => x.RawUrl).Returns("/home/index");
context.Setup(x => x.Request).Returns(request.Object);
var controller = new Mock<ControllerBase>();
var actionDescriptor = new Mock<ActionDescriptor>();
var controllerContext = new ControllerContext(context.Object, new RouteData(), controller.Object);
var filterContext = new AuthorizationContext(controllerContext, actionDescriptor.Object);
var sut = new myClass();
// act
sut.OnAuthorization(filterContext);
// assert
Assert.IsInstanceOfType(filterContext.Result, typeof(RedirectResult));
var redirectResult = (RedirectResult)filterContext.Result;
Assert.AreEqual("https://www.example.com/home/index", redirectResult.Url);
Yes, I'd use Moq and create a Mock<AuthorizationContext>. You'll need a series of mock objects to setup the fake request, most notably to specify a NameValueCollection of fake headers.
var request = new Mock<HttpRequestBase>();
request.SetupGet(c => c.Headers).Return(new NameValueCollection{ /* initialize values here */});
request.SetupGet(c => c.IsSecureConnection).Return(/*specify true or false depending on your test */);
var httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.Request).Return(request.Object);
var filterContext = new Mock<AuthorizationContext>();
filterContext.SetupGet(c => c.HttpContext).Return(httpContext.Object);
var myclass = new myClass();
myClass.OnAuthorization(filterContext.Object);
(sorry if syntax or usage is slightly off; doing this from the top of my head)
You may need to go in and mock any additional members on filterContext that HandleNonHttpsRequest invokes. I have two recommendations for going about this, as it can sometimes be a hassle if the method you are testing is doing lots of complex stuff on filterContext: 1) check visually and, if it's straight forward enough, mock all the invoked pieces 2) create the myClass.OnAuthorizationRequest, but don't implement any code yet other than the call to HandleNonHttpsRequest. Keep running the test and fixing missing/incorrectly mocked members until the test passes. Then implement your actual logic for OnAuthorizationRequest, testing and fixing (rinse repeat) until it passes.
I encountered an issue with the accepted solution using ASP.NET MVC 4. To resolve it I mocked the http context Items attribute otherwise the sut.OnAuthorization was causing an object is undefined exception:
MockHttpContext.Setup(x => x.Items)
.Returns(new System.Collections.Generic.Dictionary<object, object>());

Categories

Resources