Mock User Agent - c#

I'm writing unit tests in which I need a fake HttpContext. I used the HttpSimulator from Phil Haack (http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx).
But an function in the Sitecore api throws an exception on the following code:
request.Browser.Browser.IndexOf("IE", StringComparison.OrdinalIgnoreCase) > -1;
I debugged my code and the request.Browser.Browser is empty. I tried to fill the property with Moq but I get an exception. I also tried to add it as a header.
My code looks like this:
using (HttpSimulator simulator = new HttpSimulator("/", "localpath"))
{
//NameValueCollection nvc = new NameValueCollection { { "User-Agent", "IE" } };
//simulator.SimulateRequest(new Uri("http://www.foo.bar"), HttpVerb.GET, nvc);
simulator.SimulateRequest();
var browserMock = new Mock<HttpBrowserCapabilities>();
browserMock.SetupAllProperties();
//browserMock.SetupProperty(b => b.Browser, "IE");
HttpContext.Current.Request.Browser = browserMock.Object;
}
Does anyone know how i can mock this property?

Actually this is possible - you can set the Browser property directly on the request:
httpSim.SimulateRequest(new Uri("http://www.test.com"));
HttpContext.Current.Request.Browser = new HttpBrowserCapabilities
{
Capabilities = new Dictionary<string,string>
{
{"majorversion", "8"},
{"browser", "IE"},
{"isMobileDevice","false"}
}
};

This can not be done, you will have to use the HttpContextBase e.d. classes in MVC. Turns out unit testing with web forms is messy(?)

Related

AdWords API in ASP.NET. Can I avoid using the `user` object?

The story is: I am building a Node application, but I need data from Google AdWords. Since there is no official Node library and I couldn't get the unofficial ones to work I wanted to create a REST API in ASP.NET. So far this is what I have:
[HttpGet]
public IEnumerable<string> Get()
{
TargetingIdeaSelector selector = new TargetingIdeaSelector
{
requestType = RequestType.IDEAS,
ideaType = IdeaType.KEYWORD,
requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
}
};
// Set selector paging (required for targeting idea service).
Paging paging = Paging.Default;
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter
{
queries = new String[] {
"bakery", "pastries", "birthday cake"
}
};
var searchParameters = new List<SearchParameter>
{
relatedToQuerySearchParameter
};
TargetingIdeaPage page = new TargetingIdeaPage();
page = targetingIdeaService.get(selector);
return new string[] { "value1", "value2" };
}
I basically grabbed the code from the docs. The problem is that the targetingIdeaService is not defined. If I try to take a look at a code sample it looks like this:
public void Run(AdWordsUser user, long? adGroupId) {
using (TargetingIdeaService targetingIdeaService =
(TargetingIdeaService) user.GetService(AdWordsService.v201802.TargetingIdeaService)) {
// Create selector.
TargetingIdeaSelector selector = new TargetingIdeaSelector();
selector.requestType = RequestType.IDEAS;
selector.ideaType = IdeaType.KEYWORD;
selector.requestedAttributeTypes = new AttributeType[] {
AttributeType.KEYWORD_TEXT,
AttributeType.SEARCH_VOLUME,
AttributeType.AVERAGE_CPC,
AttributeType.COMPETITION,
AttributeType.CATEGORY_PRODUCTS_AND_SERVICES
};
List<SearchParameter> searchParameters = new List<SearchParameter>();
// Create related to query search parameter.
RelatedToQuerySearchParameter relatedToQuerySearchParameter =
new RelatedToQuerySearchParameter();
relatedToQuerySearchParameter.queries = new String[] {
"bakery", "pastries", "birthday cake"
};
searchParameters.Add(relatedToQuerySearchParameter);
And a lot more code. The point is they made it in a function, and are passing a user object into it. Now I will not have said object. Unless it's needed. Then I'm screwed. But I need to get this service up and running. This is the only missing step, other than that it should work.
So my question is: Does anyone see a way around it?
The AdWordsUser object contains the authentication you need to connect to the API. Without it your app will have no idea of which AdWords account and OAuth refresh token to supply to the TargetingIdeaService.

How to mock HttpContext (ControllerContext) in Moq framework, and have session

I want to test my MVC application, and I want to mock HttpContext. I'm using Moq framework, and here is what I've done to mock HttpContext:
[SetUp]
public void Setup()
{
MyUser myUser = new MyUser();
myUser.Id = 1;
myUser.Name = "AutomatedUITestUser";
var fakeHttpSessionState =
new FakeHttpSessionState(new SessionStateItemCollection());
fakeHttpSessionState.Add("__CurrentUser__", myUser);
ControllerContext mockControllerContext = Mock.Of<ControllerContext>(ctx =>
ctx.HttpContext.User.Identity.Name == myUser.Name &&
ctx.HttpContext.User.Identity.IsAuthenticated == true &&
ctx.HttpContext.Session == fakeHttpSessionState &&
ctx.HttpContext.Request.AcceptTypes ==
new string[]{ "MyFormsAuthentication" } &&
ctx.HttpContext.Request.IsAuthenticated == true &&
ctx.HttpContext.Request.Url == new Uri("http://moqthis.com") &&
ctx.HttpContext.Response.ContentType == "application/xml");
_controller = new SomeController();
_controller.ControllerContext = mockControllerContext; //this line is not working
//when I see _controller.ControllerContext in watch, it get's me
//_controller.ControllerContext threw an exception of type System.ArgumentException
}
[Test]
public void Test_ControllerCanDoSomething()
{
// testing an action of the controller
// The problem is, here, System.Web.HttpContext.Current is null
}
Because my application uses Session to hold user data and authentication info in almost every action method, thus I need to set HttpContext and inside it I need to set Session and put __CurrentUser__ inside session, so that action methods would have access to faked logged in user.
However, HttpContext is not set and it's null. I've searched a lot and I couldn't find my answer.
What might be wrong?
Update:
I also test below line, and get same result
_controller.ControllerContext = new ControllerContext(
mockControllerContext.HttpContext, new RouteData(), _controller);
Judging by this answer: Mocking Asp.net-mvc Controller Context
It looks like you need to mock the Request itself, as well as the properties of the request object.
e.g.
var request = new Mock<HttpRequestBase>();
etc (the full code is in the linked answer).

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 would you detect the current browser in an Api Controller?

I'm trying to detect the current web browser within one of my Api Controllers in my program using MVC4. Everywhere I look people say to use Request.Browser, however I can't get that to work. Any suggestions or is there something I'm overlooking?
You can use the HttpBrowserCapabilities in System.Web like this
var userAgent = HttpContext.Current.Request.UserAgent;
var userBrowser = new HttpBrowserCapabilities { Capabilities = new Hashtable { { string.Empty, userAgent } } };
var factory = new BrowserCapabilitiesFactory();
factory.ConfigureBrowserCapabilities(new NameValueCollection(), userBrowser);
//Set User browser Properties
BrowserBrand = userBrowser.Browser;
BrowserVersion = userBrowser.Version;
This relies on browscap.ini in Windows/System32/inetsrv/ or Windows/SysWOW64/inetsrv for definitions.
This article may also help - http://stephenwalther.com/archive/2010/03/05/use-asp-net-4-browser-definitions-with-asp-net-3-5
You could do something like following too from within the Web API's action:
System.Net.Http.HttpRequestMessage currentRequest = this.Request;
System.Net.Http.Headers.HttpHeaderValueCollection<System.Net.Http.Headers.ProductInfoHeaderValue> userAgentHeader = currentRequest.Headers.UserAgent;

Getting Cannot access a closed Stream when unit testing Nancy

I am getting "Cannot access a closed Stream" when unit testing a Nancy web app.
My module is as follow:
public class MainModule : NancyModule
{
public MainModule()
{
Get["/{Name}"] = p =>
{
var command = this.Bind<MainCommand>();
return Response.AsJson(command.ExecuteGetMessage());
};
}
}
And my test is:
[Test]
public void Should_return_welcome_message()
{
// When
var bootstrapper = new DefaultNancyBootstrapper();
var browser = new Browser(bootstrapper);
BrowserResponse browserResponse = browser.Get("/", with =>
{
with.HttpRequest();
});
Console.WriteLine(browserResponse.StatusCode);
Console.WriteLine(browserResponse.Body.ToString());
// Then
Assert.AreEqual(HttpStatusCode.OK,browserResponse.StatusCode);
}
UPDATE: I am getting StatusCode = NotFound and the exception happens when trying to access browserResponse.Body.
I had a look at the Nancy forum and also here at StackOverflow.
I tried this solution: Nancy test doesn't find route in other assembly
but still not working.
When I run the test in debug mode I see that my module is been called but I still cant check the returned value.
What should I do in order to get it working?
Thanks
Ademar
You are getting a NotFound response because the route you have defined is different from the route you have called.
You are calling / in your test, but the module has a route of /{Name}.
The exception is because there is no body with a NotFound response.
Update your test to something like:
var bootstrapper = new ConfigurableBootstrapper(c=>c.Module<MainModule>());
var browser = new Browser(bootstrapper);
BrowserResponse browserResponse = browser.Get("/ademar", with =>
{
with.HttpRequest();
});
* Updated to include source from the comment *

Categories

Resources