Unit Testing HttpContext overwrites behavior of ISitecorecontext - sitecore

In my test class i mocked the sitecore context like below to get items from my fake database:
ISitecoreContext _sitecoreContext = new SitecoreContext();
After this I tried to switch the logged in user as below :
using (new Sitecore.Security.Accounts.UserSwitcher(#"extranet\John", true))
{
// Do something
}
Eveything is working fine until I needed to set the value of HttpContext.Current which I added before the instantiation of sitecore context object
HttpContext.Current = new HttpContext(
new HttpRequest("", "http://tempuri.org", ""),
new HttpResponse(new StringWriter())
);
Now when I tried to debug my code, the line that switched another user is throwing an error
Value cannot be null, parameter name : folder
Why is it happening? Does the httpcontext overwrites the context of isitecorecontext?

Related

How do I unit test model validation in controllers decorated with [ApiController]?

As pointed out in this anwer to Asp.Net Core 2.1 ApiController does not automatically validate model under unit test, the automatic ModelState validation that ASP.NET Core 2.1's ApiControllerAttribute gives us only works when actualyy requestion the action at runtime, not by calling it with an invalid parameter in a unit test.
However, I still want to test if my action actually returns a BadRequestResult when supplying an incorrect model. Is there any way of doing this? I get that I can still manually check if ModelState.IsValid is false, and returning BadRequest() myself, but that kind of defeats the point of the automatic validation.
Am I stuck manually checking ModelState.IsValid after all, or is there a way to make use of the new ApiControllerAttribute model validation in a unit test?
If you want to validate that the api's are returning a badrequest when the data annotations are broken then you need to do an api integration test.
One nice option is to run the integration tests via an in-memory client using the TestServer
Here's an example:
//arrange
var b = new WebHostBuilder()
.UseStartup<YourMainApplication.Startup>()
.UseEnvironment("development");
var server = new TestServer(b) { BaseAddress = new Uri(url) };
var client = server.CreateClient();
var json = JsonConvert.SerializeObject(yourInvalidModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");
//act
var result = await client.PostAsync("api/yourController", content);
//assert
Assert.AreEqual(400, (int)result.StatusCode);
If you only need to make sure that the annotations is proper setup you can manually trigger the validation via the TryValidateObject method
var obj = new YourClass();
var context = new ValidationContext(obj);
var results = new List<ValidationResult>();
var valid = Validator.TryValidateObject(obj, context, results, true);

Salesforce APEX Unit Test Error with REST Services / Error at SELECT of Case Object

I've succeeded to successfully construct a REST API using APEX language defined with an annotation: #RestResource.
I also wrote a matching Unit test procedure with #isTest annotation. The execution of the REST API triggered by a HTTP GET with two input parameters works well, while the Unit Test execution, returns a "null" value list resulting from the SOQL query shown below:
String mycase = inputs_case_number; // for ex. '00001026'
sObject[] sl2 = [SELECT Id, CaseNumber FROM Case WHERE CaseNumber = :mycase LIMIT 1];
The query returns:
VARIABLE_ASSIGNMENT [22]|sl2|[]|0x1ffefea6
I've also tried to execute it with a RunAs() method (see code below), using a dynamically created Salesforce test user, not anonymous, connected to a more powerful profile, but still receiving a "null" answer at the SOQL query. The new profile defines "View All" permission for Cases. Other SOQL queries to objects like: "User" and "UserRecordAccess" with very similar construction are working fine, both for REST APEX and Test APEX.
Is there a way to configure an access permission for Unit test (#isTest) to read the Case object and a few fields like: Id and CaseNumber. Is this error related to the "Tooling API" function and how can we fix this issue in the test procedure?
Code attachment: Unit Test Code
#isTest
private class MyRestResource1Test {
static testMethod void MyRestRequest() {
// generate temporary test user object and assign to running process
String uniqueUserName = 'standarduser' + DateTime.now().getTime() + '#testorg.com';
Profile p = [SELECT Id FROM Profile WHERE Name='StandardTestUser'];
User pu = new User(Alias='standt',Email='standarduser#testorg.com',LastName='testing',EmailEncodingKey='UTF-8',LanguageLocaleKey='en_US',LocaleSidKey='en_US',ProfileId=p.Id,TimeZoneSidKey='America/New_York',UserName=uniqueUserName);
System.RunAs(pu) {
RestRequest req = new RestRequest();
RestResponse res = new RestResponse();
req.requestURI = '/services/apexrest/sfcheckap/';
req.addParameter('useremail','testuserid#red.com');
req.addParameter('casenumber','00001026');
req.httpMethod = 'GET';
RestContext.request = req;
RestContext.response = res;
System.debug('Current User assigned is: ' + UserInfo.getUserName());
System.debug('Current Profile assigned is: ' + UserInfo.getProfileId());
Test.startTest();
Map<String, Boolean> resultMap = MyRestResource1.doGet();
Test.stopTest();
Boolean debugflag = resultMap.get('accessPermission');
String debugflagstr = String.valueOf(debugflag);
System.assert(debugflagstr.contains('true'));
}
}
}
Found a solution path by using: #isTest(SeeAllData=true)
See article: "Using the isTest(SeeAllData=true) Annotation"
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_seealldata_using.htm

MVCContrib TestHelper and User.Identity.Name, Server.MapPath and Form Collection

I am new to MVCContrib Testhelper and mocking with Rhino.
I am needing assistance with unit testing a controller which relies on User.Identity.Name, Server.MapPath and Form Collection.
I started off with
var controller = new SubmitController();
var builder = new TestControllerBuilder();
builder.InitializeController(controller);
I found this post for setting User.Identity.Name
controller.ControllerContext = TestHelper.MockControllerContext(controller).WithAuthenticatedUser("domain\\username");
At this point, in my controller i am now able to get to the User.Identity. The problem then became how to i set Form Collection variables. Setting
builder.Form.Add("testvar","1");
no longer worked. It seemed that now I had to access via
controller.HttpContext.Request.Form.Add("testvar","1)
This seemed to work, but at this point, i was no longer using builder(TestControllerBuilder) above.
I then had to mock Server which raised up more issues. How can I continue to use builder but use mocks or stubs for httpContext, HttpRequest, Server etc. I was sort of expecting that builder would have methods for setting expected values for HttpRequest, Server etc.
Thanks
When you replaced the controller's ControllerContext that removed the MVCContrib context. Try something like this:
using MvcContrib.TestHelper;
using MvcContrib.TestHelper.Fakes;
using Rhino.Mocks;
...
var builder = new TestControllerBuilder();
builder.Form.Add("testvar", "1");
builder.HttpContext.User = new FakePrincipal(new FakeIdentity("UserName"), new string[] { "Role" });
builder.HttpContext.Server.Stub(x => x.MapPath(Arg<string>.Is.Anything)).Return("Value");
builder.InitializeController(controller);

First Unit Tests! ASP.NET MVC with Repositories causing errors

I am very new to Unit Testing, so I am starting on my first set of tests today. I am using the Library JustMock from Telerik. Though any unit testing information is good. I am having a bit of trouble with an interface service that passes through my method. Below is my MembershipController.Register(model) method...
[CaptchaValidator]
[HttpPost]
public ActionResult Register(Models.Membership.Registration model)
{
// just for good mesure, truncate any spaces that are given
System.Text.RegularExpressions.Regex.Replace(model.Email, #"\s", "");
if (ModelState.IsValid)
{
// Attempt to register the User and return any applicable status that has to do
// with the result.
var createStatus = membershipService.RegisterMember(model.Email, model.Password);
// if the member is able to be created successfully, log them in now and begin the
// authentication portion of the registration, otherwise, display the registration
// errors and return to the view.
if (createStatus == Membership.MemberCreateStatus.Success)
{
formsAuthentication.SignIn(model.Email, false /* createPersistentCookie */);
return RedirectToAction("Success");
}
else
{
ModelState.AddModelError("", Membership.Validator.ErrorCodeToString(createStatus));
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
And here is the paltry test I am trying to run...
[TestMethod]
public void Register_Post_ReturnsRedirectOnSuccess()
{
// Arrange
var controller = Mock.Create<Web.Controllers.MembershipController>();
var repository = Mock.Create<Membership.IMembershipService>();
Mock.Arrange(() => repository.RegisterMember("acceptible#email.com", "acceptiblePassword")).Returns(Membership.MemberCreateStatus.Success);
// Model
var model = new Web.Models.Membership.Registration
{
Email = "acceptible#email.com",
Password = "acceptiblePassword",
ConfirmPassword = "acceptiblePassword"
};
// Act
var result = controller.Register(model);
// Assert
Assert.IsInstanceOfType(result, typeof(RedirectToRouteResult));
}
The test fails because membershipService is resolving as null. I'm not sure what to do here. This is my first forray into the Unit Testing aspect of ASP.NET MVC. Can anyone give me some advice?
I am using Ninject to inject IMembershipService through the Constructor. It is implemented by the class MembershipService. The code runs fine when I run it, but the unit tests fail.
I don't see you passing repository anywhere into your controller. Normally you would have IMembershipService as a parameter in your controller's constructor that you can then pass in when needed or use MVC's Service Locator to grab the Ninject instance and pass it in.
:)

How to test binders/property editors used on spring 2.5 controllers

I have an annotated controller with a method that expects a model and a binding result
#RequestMapping(method = RequestMethod.POST)
public ModelAndView submit(#ModelAttribute(“user”) User user, BindingResult bindingResult) {
//do something
}
How do I test the binding result? If I call the method with a user and a binding result then I'm not testing the binding process. I figure there myst be something that takes a MockHttpServletRequest and returns the model and the binding result, any suggestions?
Are you trying to test the binding (which happens before this method would be called) or are you trying to test the "submit" handler method?
You can test the binding with something like this:
#Test
public void testHandlerMethod() {
final MockHttpServletRequest request = new MockHttpServletRequest("post", "/...");
request.setParameter("firstName", "Joe");
request.setParameter("lastName", "Smith");
final User user = new User();
final WebDataBinder binder = new WebDataBinder(user, "user");
binder.bind(new MutablePropertyValues(request.getParameterMap()));
final ModelAndView mv = controllerTestInstance.submit(user, binder.getBindingResult());
// Asserts...
}
You will probably find the spring-test-mvc project very relevant to what you're trying to achieve. The project is usable today and is quite simple overall but there will be some changes along the way, so if you need a stable API then this isn't for you just yet.