We are controlling access to our application's resources and actions by using ThinkTecture's MVC ClaimsAuthorizeAttribute and would like to be able to include some unit test coverage using Moq.
Ideally, I'd like to write a test which requests a controller action decorated with:
[ClaimsAuthorize("operation_x", "resource_1")]
... so as to enter our AuthorizationManager's CheckAccess override method during execution of the test.
Our CheckAccess override simply gets the action and resource from the incoming AuthorizationContext ("operation_x" and "resource_1") and determines whether the Principal has the resource/action combination as a claim and returns true if a match is found.
The test would pass or fail based on the result of our CheckAccess override.
Most of the examples I've found online are about unit testing custom Authorize attributes or testing whether a controller action has been decorated by an AuthzAttribute. There don't seem to be many examples of testing ThinkTecture's ClaimsAuthorize attribute.
Is it even possible to achieve what I've described? If so, please advise!
Thanks
You may be looking to do more work than necessary - you don't need to test ThinkTecture's ClaimsAuthorizeAttribute, because ThinkTecture have already done that. You should write tests which test your own code - namely the outcome of the actions performed inside your override of CheckAccess.
If you want to check whether the ThinkTecture attribute works as it should, you should look into setting up an integration test which causes the controller action in question to be invoked.
Related
The execution context that is injected to a function (https://github.com/Azure/azure-functions-host/wiki/Retrieving-information-about-the-currently-running-function), is it possible to get it in some other helper libraries.
I want to get the InvocationId of the current function in some other libraries. For e.g. let's say I have written a logger and I need to add the Invocation ID for every log. One trivial way to achieve this would be to pass the Invocation ID from the function to all the helpers, but it may not be possible especially if one is working with legacy code.
In App services we could solve this problem by getting access to the HttpContext via the IHttpContextAccessor.
Is there any alternative to this in Azure function?
I'm trying to run a SoapUI test-suite against two different endpoints and I do this by triggering two testrunner command and supply two different "-e" argument values.
The problem is that each of my test cases uses one API that I am testing, for which I do need to use the endpoint that is being passed under -e argument, and another API that should remain static. (The 2nd API is a helper API which sets up the environment for the first API to be able to work). So if I use the -e argument it breaks my tests because it forces the 2nd API to the same endpoint as the first API.
What I've tried so far is using the following groovy script to force endpoint value for specific Test Steps, however it's being ignored or maybe the script runs before the endpoints gets set, I'm not sure.
TestSuite setup script:
def testCases = testSuite.getTestCaseList()
for(testCase in testCases)
{
def testSteps = testCase.getTestStepList()
for(testStep in testSteps)
{
if(testStep.name == "my name")
{
testStep.setPropertyValue('endpoint','http://force.it');
}
}
}
What else can I do to overcome this issue to avoid duplicating my tests?
If you're right seems that e argument overrides all endpoints inclusive the ones you set in the setup script.
Then I purpose the follow approach for your case. SOAPUI as probably you already know has properties at different levels (testSuite, testCase, project, global) and you can use this properties to share information between your tests.
The thing is that you can use this properties to set your endpoints and pass the properties values in the testrunner command.
Set the endpoint for all your test request which test your 1st API using a global property:
${#Project#endpointAPI1}
And for the 2nd API set the endpoint url as:
${#Project#endpointAPI2}
Note: If you don't want to set the endpoints one by one you can use a groovy script testStep similar to the one you show in your question.
Once this is set, then you can invoke the testrunner for your both cases using the properties:
Then to test your cases you can add the follow properties, with -P properties are added at project level.
First endpoint for api1
-PendpointAPI1=http://one_endpointAPI1.com -PendpointAPI2=http://endpointAPI2.com
Second endpoint for api1
-PendpointAPI1=http://second_endpointAPI1.com -PendpointAPI2=http://endpointAPI2.com
Note that I use also a variable for endpoint API2 however if this is static and not change between both tests instead of using ${#Project#endpointAPI2} you can set directly the url for this service and pass only the property -PendpointAPI1.
Hope it helps,
Before I added [Authorize] filters for each controller, I created test cases and made them pass. Now I have added said filter on each controller's method but they still pass, but I think they shouldn't since there is no logged user. Am I not seeing something?
PS: I haven't mocked Identity 2.0
Edit:
Basically I'm mocking a repository, through the unit of work pattern. In my unit test, I get a reference to the List the mock repository uses, in order to test.
[TestMethod]
public async Task CanCreateCustomerAndRedirectToDetails() {
// Arrange
Customer customer = NewCustomer(); // Gets a new customer that is NOT on the list
CustomerCreateViewModel viewModel = Mapper.Map<CustomerCreateViewModel>(customer); // Maps to viewmodel
// Act
RedirectToRouteResult result = (RedirectToRouteResult) await Controller.Create(viewModel); // Sends to controller
// Assert
// Up to this point, Customers is the mock repository's list. so it should contain the new created customer since the controller should call the insert method
// Normally, the assertion should pass. But after I implemented [Authorize] filter, I would expect the controller not to do anything (besides redirecting to login) and this test would fail
Assert.IsNotNull(Customers.FirstOrDefault(e => e.ID == customer.ID));
Assert.AreEqual("Details", result.RouteValues["action"].ToString());
}
There's nothing in your unit test which responds to or in any way examines the Authorize attribute. Or any attribute.
Attributes don't actually change the behavior of the method. They decorate the method in a way that other code (such as in a framework, like ASP.NET MVC) might recognize. The Authorize attribute is used by the ASP.NET MVC framework. But the attribute alone doesn't change the method.
MSTest doesn't use the Authorize attribute. So if you want to test its presence on the method, you'd need to examine it in some way. Though that shouldn't really be necessary. The functionality of the framework is already very thoroughly tested by its vendor.
All your test needs to be testing is the functionality of the method, which it is. You don't need to test the functionality of the ASP.NET Framework.
You can test attributes very effectively by unit testing the classes which define those attributes. So if you, for example, created a custom attribute (let's call it CustomAuthorize) then you would have a class defining that attribute (CustomAuthorizeAttribute) and you could unit test that class, separately from unit testing your controllers.
What would be the easiest way to setup a request/response interceptor in ServiceStack that would execute for a particular service?
A request filter (IHasRequestFilter) works fine but a response filter (IHasResponseFilter) is not triggered if the service returns non 2xx status code. I need to retrieve the status code returned by the method as well as the response DTO (if any).
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application and I couldn't find a way clean way to isolate per functionality the tasks that need to be executed in those methods.
Is there some extension point in ServiceStack that I am missing that would allow me to execute some code before each service method and after each service method? A plugin would be ideal but how can I subscribe to some fictitious BeforeExecute and AfterExecute methods that would allow me to run some custom code?
UPDATE:
Just after posting the question I found out that global response filters are executed no matter what status code is returned by the service which is exactly what I needed. So one last question: Is it possible to retrieve the service type that will handle the request in a request filter? I need to check whether this service is decorated by some custom marker attribute.
I have found out a solution to my question about how to retrieve the service type in a custom request/response filter:
appHost.RequestFilters.Add((req, res, requestDto) =>
{
var metadata = EndpointHost.Metadata;
Type serviceType = metadata.GetServiceTypeByRequest(requestDto.GetType());
...
}
A custom ServiceRunner and overriding the OnBeforeExecute and OnAfterExecute methods seems to work fine but I find it pretty intrusive as the service runner need to be replaced for the entire application
Quick note, you can opt-in and choose only what requests should use a custom service runner, e.g:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(
ActionContext actionContext)
{
return useCustomRunner(actionContext.RequestType)
? new MyServiceRunner<TRequest>(this, actionContext)
: base.CreateServiceRunner<TRequest>(actionContext);
}
IHttpRequest has OperationName. I think thats what you are after.
In a previous version of serviceStack I was able to write a request filter for authorization this filter used res.ReturnAuthRequired() when I could not authorize the user. In the current version of servicestack my unit tests now return a null reference exception because ReturnAuthRequired now calls httpRes.EndServiceStackRequest(false); which then calls EndpointHost.CompleteRequest(); How can I unit test this now that there is a reference to the EndpointHost global variable? Should I not use the extension method?
Yeah the callbacks are required to support proper finalization of resources used in the request - e.g. it's required for Funq's new Request Scope support.
Anyway I've added some null checks in this commit to make it friendlier when unit testing, which will be available from the next v3.96 release onwards.