How best to mock S4 endpoints to do performance tests (load test)? - sap-cloud-sdk

This is not related to cloud sdk per se, but more regarding mocking the s4 endpoints which we usually use c sdk to query.
We want to do this for our load test, where we would not want the load test to go till s4 endpoint. We are considering using wiremock, to mock the endpoints, but the question is, whether the mocking logic in wiremock itself will contribute not in an insignificant manner to the metrics we are taking. If it would, then the metric becomes somewhwat unreliable since we want the apps performance metric not the mock framework's.
Other approach would be to use a mock server application dedicated for this, so that from app we would not have to do any mocking. Just route the call to the mock server app(using a mock destination perhaps)
My question to you guys is, have you ever encountered this use case? Perhaps yourself, or maybe from a consumer of yours. I would like to know how other teams in SAP solved this problem.
Thanks,
Sachin

In cases like yours, where the entire system (including responses from external services) should be tested, we usually recommend using Wiremock.
This is, because Wiremock is rather easy to setup and works well-enough for regular testing scenarios.
However, as you also pointed out, Wiremock introduces significant runtime overhead for the tested code and, thus, rending performance measurements of any kind more or less useless.
Hence, you could try mocking the HttpClient using Mockito instead:
BasicHttpResponse page = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK"));
page.setEntity(new StringEntity("hello world!));
HttpClient httpClient = mock(HttpClient.class);
doReturn(page).when(httpClient).execute(any(HttpUriRequest.class));
This enables fine-grained control over what your applications retrieves from the mocked endpoint without introducing any kind of actual network actions.
Using the code shown above obviously requires your application under test to actually use the mocked httpClient.
Assuming you are using the SAP Cloud SDK in your application, this can be achieved by overriding the HttpClientCache used in the HttpClientAccessor with a custom implementation that returns your mocked client, like so:
class MockedHttpClientCache implements HttpClientCache
{
#Nonnull
#Override
public Try<HttpClient> tryGetHttpClient(#Nonnull final HttpDestinationProperties destination, #Nonnull final HttpClientFactory httpClientFactory) {
return Try.of(yourMockedClient);
}
#Nonnull
#Override
public Try<HttpClient> tryGetHttpClient(#Nonnull final HttpClientFactory httpClientFactory) {
return Try.of(yourMockedClient);
}
}
// in your test code:
HttpClientAccessor.setHttpClientCache(new MockedHttpClientCache());

Related

Node.js express app architecture with testing

Creating new project with auto-testing feature.
It uses basic express.
The question is how to orginize the code in order to be able to test it properly. (with mocha)
Almost every controller needs to have access to the database in order to fetch some data to proceed. But while testing - reaching the actual database is unwanted.
There are two ways as I see:
Stubbing a function, which intends to read/write from/to database.
Building two separate controller builders, one of each will be used to reach it from the endpoints, another one from tests.
just like that:
let myController = new TargetController(AuthService, DatabaseService...);
myController.targetMethod()
let myTestController = new TargetController(FakeAuthService, FakeDatabaseService...);
myTestController.targetMethod() // This method will use fake services which doesnt have any remote connection functionality
Every property passed will be set to a private variable inside the constructor of the controller. And by aiming to this private variable we could not care about what type of call it is. Test or Production one.
Is that a good approach of should it be remade?
Alright, It's considered to be a good practice as it is actually a dependency injection pattern

Why is data access tightly coupled to the Service base in ServiceStack

I'm curious why the decision was made to couple the Service base class in ServiceStack to data access (via the Db property)? With web services it is very popular to use a Data Repository pattern to fetch the raw data from the database. These data repositories can be used by many services without having to call a service class.
For example, let's say I am supporting a large retail chain that operates across the nation. There are a number of settings that will differ across all stores like tax rates. Each call to one of the web services will need these settings for domain logic. In a repository pattern I would simply create a data access class whose sole responsibility is to return these settings. However in ServiceStack I am exposing these settings as a Service (which it needs to be as well). In my service call the first thing I end up doing is newing up the Setting service and using it inside my other service. Is this the intention? Since the services return an object I have to cast the result to the typed service result.
ServiceStack convenience ADO.NET IDbConnection Db property allows you to quickly create Database driven services (i.e. the most popular kind) without the overhead and boilerplate of creating a repository if preferred. As ServiceStack Services are already testable and the DTO pattern provides a clean endpoint agnostic Web Service interface, there's often not a lot of value in wrapping and proxying "one-off" data-access into a separate repository.
But at the same time there's nothing forcing you to use the base.Db property, (which has no effect if unused). The Unit Testing Example on the wiki shows an example of using either base.Db or Repository pattern:
public class SimpleService : Service
{
public IRockstarRepository RockstarRepository { get; set; }
public List<Rockstar> Get(FindRockstars request)
{
return request.Aged.HasValue
? Db.Select<Rockstar>(q => q.Age == request.Aged.Value)
: Db.Select<Rockstar>();
}
public RockstarStatus Get(GetStatus request)
{
var rockstar = RockstarRepository.GetByLastName(request.LastName);
if (rockstar == null)
throw HttpError.NotFound("'{0}' is no Rockstar".Fmt(request.LastName));
var status = new RockstarStatus
{
Alive = RockstarRepository.IsAlive(request.LastName)
}.PopulateWith(rockstar); //Populates with matching fields
return status;
}
}
Note: Returning an object or a strong-typed DTO response like RockstarStatus have the same effect in ServiceStack, so if preferred you can return a strong typed response and avoid any casting.

Using HttpContext.Current in WebApi is dangerous because of async

My question is a bit related to this: WebApi equivalent for HttpContext.Items with Dependency Injection.
We want to inject a class using HttpContext.Current in WebApi area using Ninject.
My concern is, this could be very dangerous, as in WebApi (everything?) is async.
Please correct me if I am wrong in these points, this is what I investigated so far:
HttpContext.Current gets the current context by Thread (I looked into the implementation directly).
Using HttpContext.Current inside of async Task is not possible, because it can run on another Thread.
WebApi uses IHttpController with method Task<HttpResponseMessage> ExecuteAsync => every request is async => you cannot use HttpContext.Current inside of action method. It could even happen, more Request are executed on the same thread by coicidence.
For creating controllers with injected stuff into constructors IHttpControllerActivator is used with sync method IHttpController Create. This is, where ninject creates Controller with all its dependencies.
If I am correct in all of these 4 points, using of HttpContext.Current inside of an action method or any layer below is very dangerous and can have unexpected results. I saw on StackOverflow lot of accepted answers suggesting exactly this. In my opinion this can work for a while, but will fail under load.
But when using DI to create a Controller and its dependencies, it is Ok, because this runs on one separated thread. I could get a value from the HttpContext in the constructor and it would be safe?. I wonder if each Controller is created on single thread for every request, as this could cause problem under heavy loads, where all threads from IIS could be consumed.
Just to explain why I want to inject HttpContext stuff:
one solution would be to get the request in controller action method and pass the needed value all the layers as param until its used somewhere deep in the code.
our wanted solution: all the layers between are not affected by this, and we can use the injected request somewhere deep in code (e.g. in some ConfigurationProvider which is dependent on URL)
Please give me your opinion if I am totally wrong or my suggestions are correct, as this theme seems to be very complicated.
HttpContext.Current gets the current context by Thread (I looked into the implementation directly).
It would be more correct to say that HttpContext is applied to a thread; or a thread "enters" the HttpContext.
Using HttpContext.Current inside of async Task is not possible, because it can run on another Thread.
Not at all; the default behavior of async/await will resume on an arbitrary thread, but that thread will enter the request context before resuming your async method.
The key to this is the SynchronizationContext. I have an MSDN article on the subject if you're not familiar with it. A SynchronizationContext defines a "context" for a platform, with the common ones being UI contexts (WPF, WinPhone, WinForms, etc), the thread pool context, and the ASP.NET request context.
The ASP.NET request context manages HttpContext.Current as well as a few other things such as culture and security. The UI contexts are all tightly associated with a single thread (the UI thread), but the ASP.NET request context is not tied to a specific thread. It will, however, only allow one thread in the request context at a time.
The other part of the solution is how async and await work. I have an async intro on my blog that describes their behavior. In summary, await by default will capture the current context (which is SynchronizationContext.Current unless it is null), and use that context to resume the async method. So, await is automatically capturing the ASP.NET SynchronizationContext and will resume the async method within that request context (thus preserving culture, security, and HttpContext.Current).
If you await ConfigureAwait(false), then you're explicitly telling await to not capture the context.
Note that ASP.NET did have to change its SynchronizationContext to work cleanly with async/await. You have to ensure that the application is compiled against .NET 4.5 and also explicitly targets 4.5 in its web.config; this is the default for new ASP.NET 4.5 projects but must be explicitly set if you upgraded an existing project from ASP.NET 4.0 or earlier.
You can ensure these settings are correct by executing your application against .NET 4.5 and observing SynchronizationContext.Current. If it is AspNetSynchronizationContext, then you're good; if it's LegacyAspNetSynchronizationContext, then the settings are wrong.
As long as the settings are correct (and you are using the ASP.NET 4.5 AspNetSynchronizationContext), then you can safely use HttpContext.Current after an await without worrying about it.
I am using a web api, which is using async/await methodology.
also using
1) HttpContext.Current.Server.MapPath
2) System.Web.HttpContext.Current.Request.ServerVariables
This was working fine for a good amount of time which broke suddenly for no code change.
Spending a lot of time by reverting back to previous old versions, found the missing key causes the issue.
< httpRuntime targetFramework="4.5.2" /> under system.web
I am not an expert technically. But I suggest to add the key to your web config and give it a GO.
I found very good article describing exactly this problem: http://byterot.blogspot.cz/2012/04/aspnet-web-api-series-part-3-async-deep.html?m=1
author investigated deeply, how the ExecuteAsync method is called in the WebApi framework and came to this conclusion:
ASP.NET Web API actions (and all the pipeline methods) will be called asynchronously only if you return a Task or Task<T>. This might sound obvious but none of the pipeline methods with Async suffix will run in their own threads. Using blanket Async could be a misnomer. [UPDATE: ASP.NET team indeed have confirmed that the Async is used to denote methods that return Task and can run asynchronously but do not have to]
What I understood from the article is, that the Action methods are called synchronously, but it is the caller decision.
I created a small test app for this purpose, something like this:
public class ValuesController : ApiController
{
public object Get(string clientId, string specialValue)
{
HttpRequest staticContext = HttpContext.Current.Request;
string staticUrl = staticContext.Url.ToString();
HttpRequestMessage dynamicContext = Request;
string dynamicUrl = dynamicContext.RequestUri.ToString();
return new {one = staticUrl, two = dynamicUrl};
}
}
and one Async version returning async Task<object>
I tried to do a little DOS attack on it with jquery and could not determine any issue until I used await Task.Delay(1).ConfigureAwait(false);, which is obvious it would fail.
What I took from the article is, that the problem is very complicated and Thread switch can happen when using async action method, so it is definetly NOT a good idea to use HttpContext.Current anywhere in the code called from the action methods. But as the controller is created synchronously, using HttpContext.Current in the constructor and as well in dependency injection is OK.
When somebody has another explanation to this problem please correct me as this problem is very complicated an I am still not 100% convinced.
diclaimer:
I ignore for now the problem of self-hosted Web-Api withoud IIS, where HttpContext.Current would not work probably anyway. We now rely on IIS.

Mocking Azure RoleEnvironment API with Microsoft Fakes

I'm trying to mock the Azure RoleEnvironment API with Microsoft Fakes. The problem is that I can't find a way to arrange the shims/stubs so that I can exercise the code in a unit test.
For instance, suppose I have the following code:
using Microsoft.WindowsAzure.ServiceRuntime;
// ...
Role role = RoleEnvironment.CurrentRoleInstance.Role;
int count = role.Instances.Count;
How would I mock the above with Fakes so that I can run it in a unit test?
So far my attempts fail because the RoleInstance class appears to have abstract properties with internal setters which prevents me from deriving a class from RoleInstance. This in turn prevents me from providing a shim for RoleEnvironment.CurrentRoleInstance.
BTW, I'm fully aware that relying too much on Fakes can be considered harmful. The thing is, I already have a wrapper for RoleEnvironment, together with production and test implementations. The code I'm trying to mock is in the production implementation which I want to test as well.
Unfortunately, I don't believe it is possible to isolate this code with Microsoft Fakes today. Normally, you would want to shim the RoleEnvironment.CurrentRoleInstance property to return a stub RoleInstance, that returns a stub Role. We can shim the CurrentRoleInstance property. But as you pointed out, both RoleInstance and Role are abstract classes with internal constructors, which we cannot stub with the current version of Fakes.

Can ACS Service Namespace creation be automated?

First, let me state my real problem: I've got code that makes calls to the ACS Management service, and I'd like my integration tests to be able to be run concurrently without each test run clobbering the others. That is, since multiple people / build servers might end up running these tests concurrently, if they're all using the same ACS service namespace, concurrency issues arise.
My thinking is the simplest means of achieving this would be to generate new, unique ACS service namespaces for each test runner -- but as far as I can tell, there's no automated way of creating new service namespaces (or management client keys). Am I wrong? Is there another way of going about this?
An automated method of creating new service namespaces would be extraordinarily helpful.
You are correct. That's not possible today. Maybe you can describe your scenario in more detail and there might be some alternative solutions to avoid having to recreate the namespace?
Technically it should be possible, since the Management Portal is a Silverlight application accessing a WCF RIA Service.
If you dig deep enough you'll find some useful information:
This is the Silverlight XAP for the management of Windows Azure AppFabric: https://appfabricportal.windows.azure.com/ClientBin/Microsoft.AppFabric.WebConsole.4.1.3.xap
This is the service being used when listing/creating/... namespaces etc..: https://appfabricportal.windows.azure.com/Services/Microsoft-AppFabric-Web-Services-AppFabricDomainService.svc?wsdl
And this is a piece of the DomainContext:
public sealed class AppFabricDomainContext : DomainContext
{
public AppFabricDomainContext(Uri serviceUri)
: this((DomainClient) new WebDomainClient<AppFabricDomainContext.IAppFabricDomainServiceContract>(serviceUri, true))
{
}
...
public InvokeOperation CreateServiceNamespace(IEnumerable<string> serviceNames, string parentProjectKey, string serviceNamespace, IEnumerable<string> packageKeys, string regionKey, Action<InvokeOperation> callback, object userState)
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary.Add("serviceNames", (object) serviceNames);
dictionary.Add("parentProjectKey", (object) parentProjectKey);
dictionary.Add("serviceNamespace", (object) serviceNamespace);
dictionary.Add("packageKeys", (object) packageKeys);
dictionary.Add("regionKey", (object) regionKey);
this.ValidateMethod("CreateServiceNamespace", (IDictionary<string, object>) dictionary);
return this.InvokeOperation("CreateServiceNamespace", typeof (void), (IDictionary<string, object>) dictionary, true, callback, userState);
}
}
Finding this info was the easy part, getting it to work... that's something else. Take the authentication part for example, you'll need to authenticate with Windows Live and use those credentials when calling the WCF RIA Service.
Good luck!

Resources