I am working on API testing project and have incorporated Karate to do so. Now my requirement is to create a server which will respond to the endpoint.All this is done but my requirement is to access variables defined in karate-config file in Server feature. I am unable to do so.
For example:
Feature: Sample server
Scenario: pathMatches('\variablevalue) ** methodIs('get')
def response = default_env
Note: default_env is a variable in karate-config.js file and holds some default value.
Great question, we deliberately did not want to mix the karate-config.js concept with the Karate server-side.
Normally when you instantiate a mock server via the API you can pass a Java Map and all key-values will end up as Karate variables.
But here's a trick, you can do this in the Background
* call read('classpath:karate-config.js')
And this will have the exact same effect you are looking for ! Do let me know if this works, I will make sure this is updated in the documentation.
Note that you can use JSON if all you need is some seed-data:
* def cats = read('cats.json')
Related
I try to setup an integration/API test suite with Karate and consider to use Karate Netty for mocking required services. For the test setup the system under test A (a Spring Boot app) is started up completely. The Karate tests are then executed by a Maven test run against this instance.
The service A depends on multiple other services these needs to be mocked away for the tests. To do so my idea was to configure a running Karate Netty standalone instance as HTTP proxy (done by JVM args of the service A).
Now my idea was to create one test feature file: xyz-test.feature
And the required mocks for this file are defined in an associated mock feature file: xyz-mock.feature
(The test scenarios are rather complex and the responses of the external services could vary)
This means for a full test run I need to load up a couple of mock feature files. So:
What is the matching strategy for multiple mock feature files? Which scenario wins, so to say.
Is there any way to ensure, that the right mock file is used for the associated test file?
(Clearly I can reconfigure the running standalone instance and advice it to use xyz-mock.feature next.
But this would stop me from using parallel execution for my API tests, right?)
I already thought about reusing the Correlation-Id which I can send in for each test and then match against this in the mock file (it is also sent to all called services). But:
Is there a way to define a global matcher per mock file?
It sounds like you need only one mock file. You could boot 2 on different ports if you wanted, but there is no way to "merge" them into one port - if that is what you were looking for.
In my experience, you will be able to have a single mock take care of all your edge cases. This is because Karate's approach is un-conventional: you pretty much write a stateful server. But by keeping variables in memory and some clever JSON-path, you can simulate CRUD with very few lines of code: https://github.com/intuit/karate/tree/master/karate-netty#background
You can use only one at a time, by design
Given the above limitation, here's an interesting idea: add something like an extra pathMatches('/__test/reset') scenario that cleans-up your state and sets the Background variables to things like * def cats = []. Now in each feature, just call the special "reset" URL at the start. The good thing is Karate is thread-safe. Another idea as you said is you can maintain two or three different variables and use some logic to "route" based on a header, again very easy IMO. Use a map of maps, e.g:
def data = { cats1: {}, cats2: {}, cats3: {} }
And you can get the header, e.g. if it is mode: cats1
* def mode = karate.get('requestHeaders.mode[0]')
* def cats = data[mode]
not sure if this answers your question, but if the last Scenario has an "empty" description, it is a "catch all" and can in theory delegate to another server (or mock): https://github.com/intuit/karate/tree/develop/karate-netty#proxy-mode
Your question is a little confusing, so you may have to edit and re-word it if I haven't understood.
EDIT: using multiple mock files should be possible in 1.1.0 onwards: https://github.com/intuit/karate/issues/1566
One of the param for my API is security related and linked to the environment on which the test would run , essentially it will be dynamic.
Since this is security related, I have an internal rest API that provides this data.
I want to understand what is the effective way of getting this data in Karate feature?
I have tried two different ways:
1. Defined a java util and invoke the java type and def variable for holding the data
Defined a Util method as part of karate-config.js
In karate-config.js
function getSomeData(someValue) {
return Java.type('xyz.abc.util.MyUtil');
}
In the feature file
defined a JS
* def dataFromJS = read('classpath:com/xyz/util/js_that_invokes_rest.js')
I want to understand if there is a pattern of how this should be done or if there is an explicit support in Karate for doing this?
I have an internal rest API
Well. Did you just forget that Karate is all about making REST requests !? :)
Please create a re-usable feature, make that REST call, define the variables that you need and now you can call it from other features.
Please refer to the documentation: https://github.com/intuit/karate#calling-other-feature-files
I have a playframework project that has reached beta/user testing.
For this testing we require test data to exist in the environment
I am looking for a way to automate this via scripts.
The best way will be via call's to the API passing the correctly shaped data based on the models in the project (thus dependant on the project not external).
Are there any existing SBT plugins that I could utilise that would be able to create the appropriate JSON and pass it to the API to setup the environment
Why do you need a plugin for this? I think what you want to do is to have a set of Json, then call the end-points and see what is the response from the back-end. In case of "setting up" based on a call that has a Json, you could use FakeRequest in your tests:
val application = newGuiceApplicationBuilder().build()
val response = route(application, FakeRequest(POST, "/end-point")).get
contentAsString(response) must include("where is Json")
In your test you can also test the response from the back-end and the Json you are feeding it:
Create a set of Json using Writes, based on a case class you are using in the back-end. You could also purposely create an invalid Json as well, that misses a field for example; or has an invalid structure.
Use Table driven testing and sending FakeRequest with the body/header containing your Json; and then checking it against the expected results.
I'm on the move, when I get home, I can write an example code here.
Just like how the response information can be accessed through response, responseHeaders etc, is there any way to access the request information? I noticed that request information is not available through variables. Are there are any workarounds to access this information?
I understand that we build the request ourselves in the test scenario using the Given, When steps, so it may sound redundant. The reason I'm looking for this is I would like to access the complete request details Karate would've built using our test definition. The idea is to make this information available to a java class which can be called through the Java Interop. More specifically, I'm trying to build a swagger request and response validator to be used from karate.
The workaround I am using is to explicitly create variables like apipath and apimethod and use them with path and method. This does the job, but still one has to ensure that these variables are explicitly set. It will be cleaner if whatever request Karate built is just accessible through a variable.
Please raise a feature request. We can look at making this available as karate.request or similar.
I'm writing functional test and having difficulty mocking http:request-config with oauth2. It failed at requesting for token. I tried moving the config to a separate file and create a different config in src/test/resources and include only the test config when testing. Now it complains about "name must be unique" - how do I get around this?
Be sure that your getConfigFiles() override does not include the configuration file that contains the original . This means it will need to be in a separate file from the one containing the flow you are testing.
Another method is to use a mock HTTP server such as sham-http.
In order to test Mule application you can use MUnit:
http://developer.mulesoft.com/docs/display/current/MUnit
It will allow you to mock message processors.
Now, config elements are top level elements. Those can not be mock.
I would suggest you take a look to documentation to see if the tool fit your needs.
HTH