Brief discussion on application of Wiremock combined Mock+proxy to anomaly testing
Why do I need wiremock
Recently in the NCE Automation interface test, according to the principle of covering logic as far as possible, wrote the 200+ use case, but the actual implementation of the time, probably can do 100 less, most of the completion is able to control the logical direction of the system through the incoming parameters and results of the case, that is, passing the specified parameters, call the sending Request tool, Verify the results. So what else is hard to achieve?
From the system itself, NCE is built on the underlying services of a system, his main function is the allocation of resources and scheduling, such as the interface of the cloud controller to take two machines, and then to apply for a few hard drives to hang, and then to deploy K8S components on the machine, k8s create RC and pod, etc. Given that the invocation is primarily asynchronous, it also needs to be polled, so a lot of calls are made to the external interface, as well as the logic of the result judgment. It is not so easy to invoke an external service, to get the expected results, to have an extra understanding of what is going to happen, and in some cases it is difficult to emulate and not run away from the public service. This is not just an easy problem to automate, but also a manual test to meet.
The problem of this kind of upper-level service test is generally solved. In the previous experience, need to use a mock to achieve, such as before the payment, the background depends on the Tenpay service, a lot of exceptions need to be returned by the Tenpay backstage, in addition, because the test environment is docking, tenpay do abnormal testing or environmental problems, the normal test activities to pay can not take care of themselves, So a mock is needed to reduce the dependency on the external environment. Just a mock is not enough, if a person mocks a service, then everyone goes to the mock service, if the return of the mock is abnormal, then the test activity of all people is not a way to do, if the mock return is successful, is misleading to others. So finally adopted is a mode of mock+ selection, usually the account + interface name for the dimension to control the request to access the specified destination,
If you want to do abnormal test of nce system, mock is easier to find, because the protocol is the HTTP protocol and not a self-signed protocol, so choose More, where Wiremock is a better choice, before the classmate has recommended wiremock--lightweight HTTP Mock server), try it yourself, and be easy to use. In terms of distribution, consider Python's httpserver to make a forwarding server, and after receiving the request, parse the request string forward to the desired URL and return the request back
But also to add rules to match what I feel good tired, and later found that Wiremock himself to support the real-time setting of this simpler way, then all rely on Wiremock
The first thing to do--the unified management of external access
The current service access to the external URL is in the configuration file, if each time you want to change the URL configuration point to the mock, after the test with a mock to change back is undoubtedly an inefficient approach, combined with the Wiremock proxy function want to be able to manage all possible external access
Container service before using Wiremock proxy (for example)
After using Wiremock proxy, we expect the
Follow the steps below to get the URL through the Wiremock proxy
1. Download and launch Wiremock-xx-standalone.jar
Download the Wiremock standalone and put it on a host
Basic start-up mode:
# Java-jar wiremock-1.55-standalone.jar--verbose
Java-jar Wiremock-1.55-standalone.jar–help There are some commands that you can use, add –verbose to open the verbose information output to the screen for easy debugging, when the server is used can be hung in the background as follows
# nuhup Java-jar wiremock-1.55-standalone.jar &
Welcome page is this bird-like:
Then will modify the configuration needs the proxy link cut to Wiremock, by the Wiremock default port 8080, of course, you can specify with –port. For example, you need to change the URL of kube from 10.180.155.13:8080 to 10.180.148.30:8080 (Wiremock port)
After launching the Wiremock, there are 2 folders under the directory: Mapping and __file. Mapping inside is to send and receive the rule configuration, mapping inside specified the name of the returned file, it will be removed from the __file inside the files, if the rules match, will return the corresponding content (predetermined string or file content or network error), the mismatch will return 404not found.
Here to use proxy mode, request through Wiremock Proxy, in mapping configuration proxy rules, proxy configuration and mock configuration similar, simple configuration is as follows
新建container-mapping.json文件,加入一下配置
{ "Request": { "Method":"GET", "Urlpattern":"/api/v1beta2/.*" }, "Response": { "Proxybaseurl":"http://10.180.155.13:8080/" }}
So/api/v1beta2 http request from Container->wiremock->kube, experience and direct container->kube consistent
Wiremock Log
-- to- - A: the:48.36Request Received:get/api/v1beta2/pods?labels=podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o HTTP/1.1User-agent:curl/7.26.0Host:10.180.148.30:8080Accept:*/*2015-05-30 12:09:48.76 proxying:gethttp://10.180.155.13: 8080//api/v1beta2/pods?labels=podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o
Other HTTP links can also be configured in this manner.
Automated anomaly Testing with Wiremock
Now that the external links have been included in the Wiremock control, if you want to do a network exception or specify return, you can add another rule, the URL corresponding to the request will return the specified value, but only one must take effect, such as
{ "Request": { "Method":"GET", "Urlpattern":"/api/v1beta2/.*" }, "Response": { "Proxybaseurl":"http://10.180.155.13:8080/" }}{ "Request": { "Method":"GET", "Urlpattern":"/api/v1beta2/.*" }, "Response": { "Status": $, "Body":"mocked by hzmali!\n" }}
In fact, who in the first priority to use that rule, whether to do the abnormal test every time need to change back to the normal way, if it is a manual test can be accepted, if it is automated testing, then it will be very troublesome. Fortunately, Wiremock provided the __admin/mappings/ The new interface to configure the functionality of the rule remotely.
Try to create a test.json under mapping
{"Request": {"URL":"/get/this","Method":"GET"},"Response": {"Status": $,"Body":"On disk!\n"}}
Restart Stansdalone to find the rule in effect
" Http://10.180.148.30:8080/get/this " On disk!
Call __admin/mappings/new configuration/get/this return No
' {"Request": {"url": "/get/this", "Method": "Get"}, "response": {"status": $, "body": "No!\n"}} ' http://10.180.148.30:8080/__admin/mappings/new'// 10.180.148.30:8080/get/this"NO!
Re-configure/get/this return Yes
' {"Request": {"url": "/get/this", "Method": "Get"}, "response": {"status": $, "body": "Yes!\n"}} ' http://10.180.148.30:8080/__admin/mappings/new'// 10.180.148.30:8080/get/this"YES!
Restart Standalone, the result of the previous configuration does not exist, reverting to the result of the configuration file:
" Http://10.180.148.30:8080/get/this " On disk!
You crossing presumably can guess, stanalone boot loaded the local mapping configuration to memory,/__admin/mappings/new this interface will send past rules to the latest rules, according to official documents, the latest rules will take effect:
By default, Wiremock would use the most recently added matching stubs to satisfy the request. However, in some cases it's useful to exert more control. (The exert more control refers to the use of "priority": 1, such fields to specify precedence to break the rules of the recent match, not currently How to use it)
Wiremock standalone can be set by the interface rules, and the latest effective these 2 features, the automation use case is definitely a hi-Ben message, in the simulation of external resources to return a specific message or exception, you can take such a common way:
1. Normal case: External access through the Wiremock proxy, mapping relationships are written in local configuration, Wiremock start automatically loaded, does not affect the normal function, the upper level no perception
2. Case to mock: send the desired return and match rule to the/__admin/mappings/new interface before execution, and reset the rule using proxy after completion
Simple Tesng case notation, by setting rules to control whether the return is the result of a proxy or a mock return of its own expectation
/*Webuserparametertestdata.class's Dataprovider*/@DataProvider (Name= "Sample") Public Staticobject[][] Sample () {String jsonstring= "{\" request\ ": {\" method\ ": \" get\ ", \" urlpattern\ ": \"/api/v1beta2/pods.*\ "},\" response\ ": {\" status\ ": 200,\" body \ ": \" mocked by Hzmali\ "}}"; return Newobject[][]{{jsonstring,"and"}, }; }/*Case main section*/@BeforeClass @Parameters ({"Env" }) Public voidInit (String env)throwsIOException, interruptedexception {commondata.init (env); Nce_conn=Newncehttpbiz (commondata.webhost); Mock_conn=NewMocktool (); //Print Current ResultsLog.info ("[befor test]response:" +nce_conn.getpods ()); //set the rules to put in Test .} @AfterMethod Public voidRecovermapping ()throwsioexception{//Recovery RulesString rule= "{\" request\ ": {\" method\ ": \" get\ ", \" urlpattern\ ": \"/api/v1beta2/pods.*\ "},\" response\ ": {\" Proxybaseurl\ ": \" Http://10.180.155.13:8080/\ "}}";; mock_conn.setmapping (rule); //Print the results after recoveryLog.info ("[After Test]response:" +nce_conn.getpods ()); } @Test (Dataprovider= "Sample", Dataproviderclass =webuserparametertestdata.class) Public voidSample (String rule,string expeted)throwsIOException {System.out.println (rule); //set the expected returnmock_conn.setmapping (rule); //Print the expected returnLog.info ("[Testing]response:" +nce_conn.getpods ()); }
The printed result indicates that it matches the expected
[INFO]17:32:34, [Class]ncehttpbiz, [Method]getpods, ==========call getpods=============[INFO]17:32:34, [Class]mockcase, [Method]init, [befor test]response: {"Kind": "Status", "Creationtimestamp":NULL, "Apiversion": "V1beta2", "Status": "Failure", "Message": "Invalid selector: ' podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o '; Can ' t understand ' podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o ' ", "Code": 500}[info]17:32:34, [Class]mocktool, [Method]setmapping, ==========setmapping============={"Request": {"method": "GET", "Urlpattern": "/api/v1beta2/pods.*"}, "response": {"status": $, "body": "Mocked by Hzmali"}}[info]17:32:34, [Class]ncehttpbiz, [Method]getpods, ==========call getpods=============[INFO]17:32:34, [Class]mockcase, [Method]sample, [testing]response:mocked by Hzmali[info]17:32:34, [Class]mocktool, [Method]setmapping, ==========setmapping=============[INFO]17:32:34, [Class]ncehttpbiz, [Method]getpods, ==========call getthis=============[INFO]17:32:34, [Class]mockcase, [Method]recovermapping, [after Test]response: {"Kind": "Status", "Creationtimestamp":NULL, "Apiversion": "V1beta2", "Status": "Failure", "Message": "Invalid selector: ' podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o '; Can ' t understand ' podlabel%3dapitest-d5e3e7cf9bee471f8ff642d1258e1354-go00o ' ", "Code": 500}
In actual use, such as testing deployment services, POD State is not the correct scenario, you need to query pod this interface mock off, kube other interfaces are going to proxy way, the actual use of regular meetings more complex
Postscript
The use of Wiremock also have some inconvenient place: Because is proxy, so if have the same name interface, need to use additional regular mode or new wiremock process; The current expected return is controlled by use cases, controllability is strong, for some large-grained anomaly scenario simulation is better, such as pan failure , network errors, etc., but it takes a little effort to accurately simulate the correct return in various scenarios, and it is a challenge to construct a return that conforms to the data dependency. At present only preliminary use, there are many pits did not step on, optimistic to see this way can solve some problems, and the price is not high, you can take the top of the top.
Brief discussion on application of Wiremock combined Mock+proxy to anomaly testing