This question already has answers here:
Mock HttpContext.Current in Test Init Method
(4 answers)
Closed 6 years ago.
I have Web Api controller Action method I am trying to unit test. I have one custom filter which runs before that action controller.
I have question regarding HttpContext.Current.User.Identity.Name that I am using inside my custom action filter.
It works nicely when I send my http post request from web client.
But, when I send http post request from my unit test than HttpContext.Current always complain for null
Don't understand where and what is wrong.
Anybody can please explain it?
Please note that I have seen answers at here but not sure where I need to add that code in my case.
Unit testing is not the same as calling your api through a web client.
When you are using a web client, you api is running in the context of you web server (IIS, for example) and the web server will provide the system with che "current" HttpContext.
If you call you code plain and simple from a unit test method you're not running in the context of a web server, but you're calling it simply as a method of a class. Obviously you can do it, but you need to "mock" (of fake, if you want) the current HttpContext to simulate you're running in a real web server.
Check this SO answer for the details on how to do it.
BTW, this is not the case when you run integration tests (means calling the real API throught a web client and just check the input-output results): in that case you are running your real code in a real context and everything will work fine.
HttpContext.Current is not set in a self hosted scenario like in your test.
You can however create a wrapper around HttpContext.Current and populate it before you run your test. Like this:
public static class CurrentHttpContext
{
public static Func<HttpContextBase> Instance = () => new HttpContextWrapper(HttpContext.Current);
}
And then somewhere in your test where you set up your HttpSelfHostServer, you populate the CurrentHttpContext.Instance. For example with FakeItEasy (https://github.com/FakeItEasy/FakeItEasy):
var context = A.Fake<HttpContextBase>();
CurrentHttpContext.Instance = () => context;
Then you can access CurrentHttpContext.Instance instead of HttpContext.Current in your filters:
public class MyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var context = CurrentHttpContext.Instance();
// stuff
}
}
Related
I am trying to run the following code (where fusseApp is an angularModule) :
fusseApp.run(function(URI, $http){
$http.get('/check/userLogged').then(function(response){
console.log(response);
});
PS : Actually my http call is executed in a factory and here we just have a call to this factory
The angularModule is mocked with :
angular.module('fusseApp.mainMocks', ['fusseApp', 'fusseApp.loginMocks', 'ngMockE2E', 'ngResource'])
.run(function($httpBackend, $http) {
...
$httpBackend.whenGET('/check/userLogged').respond(200,response);
My problem is that fusseApp.run is executed before the mock module is initialized. So I a have an error :
Uncaught Error: Unexpected request: GET /check/userLogged
No more request expected
This problem seems to have been raised in the jasmine unit-test, but I cannot find a solution. Is it possible to run my $http call after an event that tells me when the application is completely initialized?
My need is to check that the user is authenticated before displaying any data on screen.
maybe this can help...
.run() is always executed if you set ng-app="" in you code, its part of the boostrap process, from there on you can't stop the compile & linking process, but there's many ways to go to prevent a view from being rendered if the user is not logged in:
A) Manual angular boostraping (not so fun but feasible) can be done after authentication is ok, either use jQuery $.ajax or another lib because $http service is out the picture outside NG.
B) But in your .run() you have access to $rootScope and all of the NG services, therefore you can listen for $stateChangeStart and inside the listener perform you auth validation.
This is more or less the best practice for NG authentication, this listener keeps checking every time the user changes state, (which is good so that you can catch sessions expirations), In my code (which I use in prod in various projects) I do exactly this:
$rootScope.$on("$stateChangeStart", function(event, toState, toParams, fromState, fromParams) {
if (!AuthService.isAuthenticated()) {
$state.transitionTo("login"); // redirect to login page
event.preventDefault();
}
});
AuthService is just a simple service that returns true or false if the user is authenticated.
In my experience the best solution to hide views to unauthorized users and redirect, is to catch state change process like I show before.
Because you can decorate states these properties are accessible in the toState argument (in ui-router at least) So it's possible to do all kinds of fancy stuff like catching user roles and so on...
I'm writing some functional tests in play, however I want to test my stack isolated from other http endpoints.
Is there a mechanism for me to say "Direct WS calls to this set of canned responses" or some other way of stubbing out calls to http endpoints that won't be available for automated tests?
Alternatively, how does fakeApplication config get presented to the rest of the application so I can just set the URL to some localhost server which I'll build myself to provide canned responses
You could create a structural type that mimics the WS signature and use that in your code.
type WSLike = {
def url(url: String): WSRequestHolder
}
Then you can inject your own version of a WSLike class. In combination with a mock library I guess you could do about anything you want.
As for the second question. You could call it like this:
val url = Play.current.configuration
.getString("my.webservice.url")
.getOrElse(throw new PlayException(
"Configuration error",
"Could not find my.webservice.url in settings"))
WS.url(url)
Then in your application.conf add the correct url. You can supply a different one using the FakeApplication.
FakeApplication(additionalConfiguration =
Map("my.webservice.url" -> "http://localhost/service"))
I've read a lot about switching between multiple datasource on runtime, but as far as I understand they're already defined datasources. I'm not quite sure on how can I just asign the datasources properties on runtime from a webservice call.
I don't need to switch between datasources, just need to create only one datasource with conection data coming from a webservice.
Is there a way to retrieve these parameters from the webservice and create the datasource from that?
The policy here is to retrieve the datasource parameters from a webservice for all the projects, that way the connection data is not inside a file nor into the code, and is only manipulated by DBAs from a global security aplication.
I tried to call the web service in the same datasource file, but it didn't work.
Info:
Web service is a Soap Web service
Grails: 1.3.9
Regards.
I think that you can create a BeanPostProcessor that take care of calling your webservice and changing the settings of your dataSource.
Probably you will need to delay the session factory creation, making sure Grails won't try to use your dataSource before you have all setted up correctly.
The BeanPostProcessor will looks like:
class WebserviceDataSourceBeanPostProcessor implements BeanPostProcessor {
Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean
}
Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof DataSource){
def info = //call webservice here...
bean.username = info.username
bean.password = info.password
bean.url = info.url
//checkout more setters in: http://commons.apache.org/proper/commons-dbcp/apidocs/org/apache/commons/dbcp/BasicDataSource.html
}
return bean
}
}
And make sure you declared this Spring Bean in resources.groovy
beans = {
webserviceDataSourceBeanPostProcessor(WebserviceDataSourceBeanPostProcessor)
}
If you will have more than one project with this same config comming from a webservice you may think in the possibility of a plugin for this, reusing your code.
I am working on a Restful Web Service, which get request from client, then strip some information and insert it into the database.
When it insert to the database, it has two parts of information needed: Uri and HttpRequest.
Now I have my method like this:
public void insertDb (#Context UriInfo uriInfo, #Context HttpServletRequest request)
I am trying to do some unit testing, create a client then WebResouce.
I wonder how can I pass in the parameters in unit testing? Or should I change the params in the insertDb function?
Have you heard about Jersey Test Framework? http://jersey.java.net/nonav/documentation/latest/test-framework.html
You don't need to change signature of your method, you need to start Jersey somehow (Test Framework can help you with that) and make request to that Resource. Simple sample of this can be seen in helloworld sample, see http://search.maven.org/remotecontent?filepath=com/sun/jersey/samples/helloworld/1.10/helloworld-1.10-project.zip.
I use an IOC container which provides me with IService.
In the case where IService is a WCF service it is provided by a channel factory
When IService lives on the same machine it is able to access the same cookies and so no problem however once a WCF Service is called it needs to be sent those cookies.
I've spent a lot of time trying to find a way to send cookies using a channel factory and the only way I could find that works is the following
var cookie = _authenticationClient.GetHttpCookie();
HttpRequestMessageProperty httpRequestProperty = new HttpRequestMessageProperty();
httpRequestProperty.Headers.Add(HttpRequestHeader.Cookie, cookie.Name + "=" + cookie.Value);
using(var scope = new OperationContextScope((IClientChannel)_service))
{
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
var result = _service.Add(details);
if (result.Result == RPGResult.Success)
{
return RedirectToAction("Index", "Home", result.Id);
}
}
The problem with me using that method is that I have to know that I'm calling a WCF Service which is not always the case. I've tried writing a wrapper for the ChannelFactory that opens a new operationcontextscope when it creates a new service and various other solutions but nothing has worked.
Anyone have any experience with sending cookies over WCF Services?
I found a solution involving using SilverLight, unfortunately I'm not using silverlight, the solution is here: http://greenicicleblog.com/2009/10/27/using-the-silverlight-httpclient-in-wcf-and-still-passing-cookies/
Unfortunately standard .net doesn't contain the IHttpCookieContainerManager interface
Ideally I would be able to use something similar,i.e. I would be able to tell the channelfactory to pass a cookie whenever it opened.
If anyone has a better way to pass a token that is used for authentication that would be appreciated too.
I have a solution where I create a proxy class of IService and then every time a method on IService is called it invokes the proxy created by the channel factory but the call itself is wrapped in an operationcontextscope just like the one I have in my question.
I used the proxy factory from this link http://www.codeproject.com/KB/cs/dynamicproxy.aspx