BreadcrumbHomeResourcesBlog How To Use BlazeMeter Service Virtualization For Testing August 15, 2019 How to Use BlazeMeter Service Virtualization for TestingTest AutomationService VirtualizationBy Petr VlasekIn addition to the newly introduced UI Functional testing and 360° API Testing and Monitoring, Blazemeter now provides Service Virtualization functionality. This is a critical aspect for when the application or module you are developing and testing is dependent on the other services or systems regardless whether external or internal. Such dependencies could cause a lot of troubles during testing as it may not be easily available when you need them or they may have constraints like costs or limited control over data it returns – and all of that typically leads to unwanted trade-offs during the testing.Table of ContentsHow to Create your first Virtual ServiceImport Transactions for dependency of your applicationFrom Transactions to running Service VirtualizationPlaying with errorsIntroduction of Self-Defining Test Assets – tests that know what they needWhat about creating Service Virtualization directly in code?Table of Contents1 - How to Create your first Virtual Service2 - Import Transactions for dependency of your application3 - From Transactions to running Service Virtualization4 - Playing with errors5 - Introduction of Self-Defining Test Assets – tests that know what they need6 - What about creating Service Virtualization directly in code?Service Virtualization removes these dependencies and also helps to control the behavior of the dependencies by simulating the service using the endpoint provisioned by you - and this moves your testing to the next level. You can read this blog post on the benefits and concepts behind Service Virtualization and Service Virtualization concept in general.In this blog we'll focus on how to use Service Virtualization within the Blazemeter platform, including exploring key concepts and integrations with open source tools like CodeSV and Wiremock. As already mentioned, Service Virtualization are part of the new Blazemeter Continuous Testing platform, and you can find them under Service Virtualization tab in Blazemeter menu header.Back to topHow to Create your first Virtual Service If you access Service Virtualization for the first time, you are routed to the “Learn more” section of Service Virtualization screen that gives you basic overview about the functionality and points you to various guides and help topics to explain the concept in detail. But besides that, it also provides a quick-start experience how to create your first Virtual Service.It is as simple as taking an already existing Swagger specification, har file or .json exported from Wiremock or CodeSV and dropping this file inside the dropzone area on the top of the screen. After a few seconds, your screen switches to theService Virtualization administration and your first Virtual Service is created and ready to be run.In my example, I am using the “Sample transaction file” available via link placed just below the dropzone in the Learn More page – which is a .har file containing traffic from a hypothetical petstore.blazemeter.com application.But before we run it, let’s investigate what happened behind the scenes and with what concepts we are working on.As discussed before, Service Virtualization behaves like the real service – simulates its responses and it is represented by endpoint you have under your control. Its behavior is driven by Transactions. A single Transaction defines the HTTP request-response structure where the request part represents the request matching and the response part defines the response that should be provided when request is matched – it is following the following semantics: “if the request received by Service Virtualization matches the conditions, then return defined response”.Request matching could be defined by the exact match of the URL path, HTTP operation, by query parameters, request headers, request body, cookies or authentication. Various matching operators are available as well as ability to match request values by regular expressions (see Request Matching Examples for more details). The end goal is to return responses that appears exactly as being returned by the real service so you can use Service Virtualization instead of the real service during testing of your application.When the file was dropped into the dropzone in Learn More page, request and response data were extracted and turned into the Transactions that were automatically added to the Virtual Service created for you during the Learn More quick-start flow. You can check that by expanding the row of the newly created Virtual Service in the table – there should be 5 different transactions assigned to your Virtual Service. And these transactions will drive the behavior of the Virtual Service.In this simple example, we can keep all pre-selected default values and just press “Run Virtual Service”. After few seconds, Service Virtualization is provisioned for you in cloud and it is accessible via the endpoint. Let’s copy this endpoint to the browser and add /api/pets and press enter – congratulations, you have got your first response from your Virtual Service!It the next part, let’s take a look at an example which is much closer to real-life scenario.. Dealing with application dependencies Let’s suppose I am developing and testing my Digital Bank web application. One of its features is the “ATM Search” that is being powered by the external 3rd party service responsible for ATM Search (synapsefi.com) – it searches for the ATMs within a radius of the area provided by zip code. My application just sends request to this 3rd party API, gets search results in response and displays them nicely in user interface. Note: This Digital Bank demo application is open-source and available for your experiments - feel free to check out its source code https://github.com/asburymr/Digital-Bank. You can follow this blog post and try all of the actions by yourself.There are a couple of issues with this setup causing issues in testing:I cannot rely on the data returned from 3rd party service – what if the number of ATMs changes over time, but your test is designed according to particular number of ATMs?Service may not be available all the time.I have no control over which data it returns and how it behaves – I cannot reproduce certain cases at will or at all.There may be associated costs with using this service – which is something I would like to avoid during the testing.This is a typical scenario when your application is dealing with any dependency – which may be 3rd party or just a service on which different sitting on the opposite side of the office is working on.Back to topImport Transactions for dependency of your application As we discussed in the beginning, Transactions are the objects that drive Service Virtualization. So let’s start with them. There are many ways how to create Transactions – by importing various type of files (Swagger, har, json definitions of Wiremock and CodeSV stubs) that capture or define the HTTP traffic or API specs or manually using the editor in Transactions tab within Service Virtualization. Let’s assume I have already captured the har file that represents sample traffic to the ATM search 3rd party service.Let’s switch to the Transactions screen and drop the .har file in the dropzone area on top of the screen. The “Import Transactions” dialog opens – I have to pick a Service where my Transactions will be created. Service is an entity that represents the real service I want to virtualize and helps me to keep all assets relevant to the real service under single object – for now, we can treat is as a folder that keeps Transactions and Service Virtualization related to a particular real service under one parent. By typing a name of the Service, I can either search for the existing or create the new one – and I want to create “ATM Search” service.Also, all of the Transactions that will be created may be tagged – tags helps to organize transactions into more granular logical groups like for example “dev” for Transactions relevant to testing during the development, “regression” for stuff important for regression testing or “negative” for Transaction representing some negative behavior of the service. Let me choose tag “digital-bank” just to indicate that these ones are related to my Digital Bank application development and testing. Once the import process finishes, I will get two Transactions created in my repository. First of all, I will deep-dive into them to understand more the logic inside.One of them represents the regular case – for the request using the given path and query parameter with zip code, it returns response with content of 2 ATMs. For convenience, let’s rename this Transaction to “OK Response”.The other one is pretty similar, but returns no ATMs – it is still a valid response as it returns expected JSON structure, but simply there are no ATMs found. I may want to rename it to “Empty response” and also change the query parameter zip matching value “94204” so my Virtual Service can provide one or the other response based on the specific query parameter value send in the request.These two Transactions are enough for my basic testing – I can test whether my application correctly renders a case where some ATMs are returned (and thanks to the Virtual Service I know I can base my test assertions on the 2 ATMs being returned) and also I can test how does my application behave if there are no ATMs found – does it handle this edge case correctly? Mock will help me to figure that out. But I can do more – let’s clone the “Empty response” Transaction using the inline action in the table.I will change the cloned Transaction to return some error response – let’s pick “410 - Gone”, delete the response body and for convenience rename this Transaction to “Error response” and assign tag “negative”. This way I have defined an error behavior and I am interested if my application can recover from such error returned from the dependent service (e.g. provide some user friendly message rather than fail with some ugly stack trace output displayed over my nicely designed UI). Remember, that I am not able to test such case with the real service as I have no way how to force it to behave like this at will – but with Service Virtualization, I have it under my control pretty easily.Back to topFrom Transactions to running Service Virtualization In total, I have three different transactions and I am ready to create Virtual Service and use it for my testing. Let’s switch to Service Virtualization screen. Using the + button, I create new Virtual Service – I can define name of the Virtual Service, Service under which it belongs, location where it will be deployed (either cloud provisioned by Blazemeter or my OPL location if I need to access Virtual Service endpoint behind firewall) and whether it is going to represent http or https host. When expanded, I can select which Transactions it should host – the left side represents Transactions available in my Service, right-hand side represents what is deployed (or going to be deployed) to the Service Virtualization endpoint. In this case I will move “OK response” and “Empty response” from left to right – my Virtual Service will host these two Transactions. The “Parameters” section allows me to define what should happen if the request is not matched by Transactions inside the Service Virtualization – it can either return 404 or redirect to the real system (so I can selectively virtualize only what I defined, the rest of the traffic will be bypassed to the real system). I can also define “Think Time” which simulates additional delay in provisioning of the response. This is especially useful in software performance testing when I may want stable behavior of the application dependencies so the overall performance of my application is not affected by any network glitches or on the other hand I may be interested what it is going to happen if the dependent service providing responses in a very slow pace. But for now, I am fine with the defaults for both parameters.Now I am ready to press “Run Virtual Service” to spin it up. After few seconds I will get Virtual Service simulating the ATM Search service running in cloud. I can quickly copy the endpoint and just to experiment a bit paste it to browser and add the path and query parameter:Hitting https://atmsearchmock233-8080-default.mock.blazemeter.com/v3.1/nodes/atms?zip=94203 returns response with 2 ATMs. https://atmsearchmock233-8080-default.mock.blazemeter.com/v3.1/nodes/atms?zip=94204 on the other hand returns empty response with no ATMs https://atmsearchmock233-8080-default.mock.blazemeter.com/v3.1/nodes/atms?zip=94205 gives me 404 “No match found” as there is no matching Transaction...Now, I can reconfigure my Digital Bank application to use the Virtual Service endpoint instead of the real 3rd party service endpoint. (For those who follows this blog with hands-on trial, you can run Digital Bank Docker container with additional parameter that reconfigures application to point to a Virtual Service – in my case: docker run -p 8080:8080 -e 'IO_DEMO_BANK_ATM_HOST=atmsearchmock233-8080-default.mock.blazemeter.com' asburymr/digitalbank). Let’s check what happens inside the application.For zip code 94203 it correctly displayed two ATMs found; for 94204 correct message that no ATM has been found.Back to topPlaying with errors Now, I can go back to Service Virtualization, expand my Virtual Service in the table and check the log – it will give me an overview what requests have been sent to Virtualize and whether they were matched or not, which may help in debugging why a request is not matched.Additionally, I would like to change my Service Virtualization behavior to host the error response I created earlier. But before doing that I can take a snapshot of my current Virtual Service and store it as a Service Virtualization Template so I can later easily recall this exact configuration – which is based on hosted Transactions and Parameters. I just provide convenient name like “ATM Search normal behavior” and save it.Going back to my Virtual Service, I can just swap “OK response” and “Empty response” Transactions with “Error response” – so my service will host only the error behavior now. By pressing “Update”, the Virtual Service is being reconfigured according to the new settings.Once done, I can go back to my Digital Bank application which is still running and pointing to my Mock Service and try to search for ATM again. Now the results page shows error message indicating that something went wrong. This is acceptable for me, the search failed gracefully – no stack traces or cryptic errors are displayed.Again, for convenience I can go to Service Virtualization and create a template snapshot of this Virtual Service configuration and call it “ATM Search negative behavior” – so I have two templates keeping different behavior of my Virtual Service which allows to easily create new Service Virtualizations based on these templates. Back to topIntroduction of Self-Defining Test Assets – tests that know what they need Now, I would like to use all of what I prepared together with Blazemeter tests. Obviously, I can just wire my application to the Virtual Service, configure my Virtual Service according my needs and run tests, however Blazemeter can do some of that for free via a concept of Self-Defining Test Assets.Let’s suppose that I have two tests – one test is supposed to test the normal behavior of the application. The second test scenario is intended to test unexpected or error cases that may happen in my application. As we already know, this is represented by different Transactions and also by differentService Virtualization Templates I have created for my Digital Bank scenario. In order to be able to run these two tests I would either need to define smart matching logic, so one Virtual Service will contain all potential transactions and match them based on different test scenarios; or to define twoService Virtualizations where each service hosts different behavior for different test scenarios (but then I need to rewire my application before every test to a different Virtual Service); or before every test to manually reconfigure my single Virtual Service to host different Transactions. Self-defining test assets could to this for me automatically!In my test configuration, I can use the new section called “Service Virtualization” to define what behavior my test expects from the Service Virtualization. By enabling this section and pressing +, I can add new Virtual Service entry and define whether the selected Virtual Service should be configured according “ATM Search normal behavior” or “ATM Search negative behavior” template. So for “Normal Behavior Test” I selected “ATM Search normal behavior” template and for “Unexpected Behavior Test” I chose “ATM Search error behavior”.Once I wire my application to the Service Virtualization, I can then just execute these tests and each test during the pre-execution phase automatically reconfigures behavior of the associated Virtual Service according to the provided template. I do not need to care which set of transactions or which template is relevant to various tests – test itself declares this dependency.Using my Taurus script I could go even into bigger granularity and besides using templates I can define associated Service Virtualization behavior by sequence of Transactions or by filtering by tags. Just add one of these definitions of dependencies to your Taurus files:dependencies: services: - service: ATM Search mock-service: ATM Search Mock mock-service-template: ATM Search normal behavior dependencies: services: - service: ATM Search mock-service: ATM Search Mock transactions: - OK response - Empty response dependencies: services: - service: ATM Search mock-service: ATM Search Mock transaction-filter: tags: - negative Back to topWhat about creating Service Virtualization directly in code?The last part of this introduction to Service Virtualization is focused primarily to developers and the way how developers could use Service Virtualization directly in the code (anything what could be described by code always makes developers happy) and collaborate with non-developers via Transactions repository.Using libraries like CodeSV or Wiremock developers can define virtual services-like functionality directly in the code and leverage the advantages of Service Virtualization during development phase and build robust integration test directly in the code - i.e. to create something like this example using CodeSV (Wiremock code looks very similar).@Testpublic void testSearchATMLocations() throws Exception {forGet("https://uat-api.synapsefi.com:443/v3.1/nodes/atms").matchesQuery("zip", "94204").usingHttps(withSecureProtocol("TLS").keystorePath(KEYSTORE_PATH).keystorePassword(KEYSTORE_PASSWORD).keyPassword(KEYSTORE_PASSWORD)).doReturn(okMessage().withJsonBody(RESPONSE_EMPTY));List results = searchService.searchATMLocations("94204");assertTrue(results.isEmpty()); } This way, developer can easily and naturally define Service Virtualization in the code and they are created behind the scenes within the code runtime. This is great for developers, but how to re-use the stuff they defined in the code in Blazemeter where additional team members can contribute and add new Transactions to simulate behaviors that developer did not cover initially?It is easy, CodeSV 2.0 and our Wiremock extension provides a way to convert these in-code definitions into transactions and upload them to the Transaction Repository (directly from the code or via exported JSON file). This way, whatever developer created in the code is available out of the code scope in Transactions Repository so anybody can create Virtual Service in Blazemeter based on these Transactions and associate this Virtual Service with Blazemeter tests. In addition, any Transactions created in Transaction Repository (regardless of whether they were initially created from code or not) could be referred from code – so developers can use the stuff somebody else created and fine-tuned in the Transaction Repository.This positions Service Virtualization as a uniquely flexible solution that connects different personas participating in software development and testing and benefits from Service Virtualization.Developers can choose to use the streamlined and simple UI of Service Virtualization in Blazemeter or in-code approach using CodeSV or Wiremock, they can work together with testers who may leverage Service Virtualization intuitive UI as well as enrich their tests via Blazemeter UI or Taurus.START TESTING NOWBack to top
Petr Vlasek Product Management, BlazeMeter Petr works as Product Manager for BlazeMeter Continuous Testing platform. In past he worked in architect and product roles in areas of workload automation, application security and blockchain research. His current passion is looking for innovative ways how to take continuous testing to the next level and make it developer-friendly.