1

We want to execute component test using Karate against a SpringBoot application that uses application-demo.yml to set it´s properties. For example (application-demo.yml):

...
services:
  database:
    host: localhost
    port: 5432
spring:                  
  datasource:
    jdbcUrl: jdbc:database://${services.database.host}:${services.database.port}/database
...

Our Karate code is included within the same repo so that we can execute our component tests using a runner as part of the same CI/CD that will bring up the SprintBoot application.

We do have karate.env set to a specific environment (in this case "demo") In our karate-config.js we set common values in the config object (for example, baseURL of the SpringBoot application)

...
let config = {
  baseUrl: 'http://localhost:8082'
};             
...

Then in our environment specific karate config (karate-config-demo.js), we have additional parameters to be set in the config object. We wanted to avoid duplication of properties so we took the springboot application-demo.yml as the source of the new parameters.

...
const configYaml = karate.read('classpath:application-demo.yml');
let config = {
  database: {
    jdbcUrl: configYaml.spring.datasource.jdbcUrl
    ...
  }
};
...

By doing this, karate config object will contain values like this:

database.jdbcUrl = jdbc:database://${services.database.host}:${services.database.port}/database

which is a problem as it is not replacing the placeholders with the corresponding values from the yml file.

Got a couple of questions:

  1. As per the documentation, we can see the config object is "merged" between karate-config and karate-config-demo, so a combined object will be available for the feature files (overriding key/values if already exist). But if we try to print the content of that karate config object we can see it only shows the properties set in that karate-config-demo.js but will not show the ones from karate-config.js Is there any way to access to ALL the properties set in that config object from karate-config-demo.js ?

  2. To workaround the placeholder issue, we decided to use a Javascript function that takes a json object (config) and the yml and then replaces the placeholders ${} with the corresponding values from the yml. That function is defined in a separate file (let´s say js/replace.js) and contains a function that takes two arguments: function fn(jsonData, yamlData) and returns a json object. That json object will be used by karate-config-demo.js to return the config object as the output of the function. Something like this:

let replacePlaceholders = karate.read('classpath:js/replace.js');
config = replacePlaceholders(config, configYaml);
return config;

The problem we see is that the json objects sent as parameter to the replace function are "transformed" and they are no longer json objects within the function. rinting the jsonData at the beginning of the replace function we see this

{database={jdbcUrl=jdbc:database://${services.database.host}:${services.database.port}/database}}

We cannot parse it into a json as it´s not a proper json object. We were able to make it work by sending the string representation (JSON.stringify) of the json as parameters instead of the json object. In the javascript function we had to parse it again to json (JSON.parse). Is there any way to avoid this double transformation by passing proper json object to the javascript function ? What´s the reason of that json transformation... or are we doing something wrong here ?

Tried different options to send the json objects as parameters but no luck. They are always transformed to non-json objects.

  • can you see if this answers your questions: https://stackoverflow.com/a/75824779/143475 - my suggestion is maybe you should write a java helper to get values out of the spring context after it is booted and then pass them to karate. that might simplify things, here are some hints: https://stackoverflow.com/a/51178439/143475 – Peter Thomas Mar 26 '23 at 13:35
  • Thanks Peter for your quick response. Unfortunately the provided solution will not work for us as one of the requirements it that we should not modify the SpringBoot application code base and in this case, there are no exposed methods to get the application configuration. That´s the reason why we were taking the properties directly from their configuration yaml file (which is available as we share the repo) – Alberto Ceballos Mar 26 '23 at 15:09
  • The questions raised are not specific to the SpringBoot related environment but Karate itself: 1- Is there any way (in the environment-specific karate config file) to access the karate config object and see the same than the feature files will be able to see (ie. whatever has been set in karate-config.js + karate-config-.js) ? 2- In case you want to modify that karate config object using a javascript function (passing it as parameter to the function), we can see it is not passed as json object. Is there any transformation done? If so, what´s the underlying reason for that ? – Alberto Ceballos Mar 26 '23 at 15:10
  • look, I'm trying to help. karate's JS is very different and the first link explains the situation and a possible bug (resolved in 1.4.0.RC3). anything beyond that we urge you or the community to contribute code as it sounds like a very rare, non-typical use-case. and no, in the environment-specific config, you can't "see" the main config. it is just "appended" to the main config. you should probably try to do all your "hacks" in the main config. you can always custom read a second JS file and append it "manually" - refer comments here: https://stackoverflow.com/q/75524515/143475 – Peter Thomas Mar 26 '23 at 15:19
  • 1
    Thanks Peter. Don´t get me wrong. I really appreciate your prompt response. It´s fantastic to get first-hand answers for all of our questions. Regarding the transformation of the config object using javascript function, just tried with 1.4.0.RC3 (as recommended) and confirmed that works fine. Again, thanks a lot for your comments and sorry if that was already answered and I missed it. – Alberto Ceballos Mar 26 '23 at 19:26
  • great to hear that 1.4.0.RC3 worked, I'll add an answer for the benefit of others in the future – Peter Thomas Mar 27 '23 at 03:08

1 Answers1

1

The reason that JSON did not behave the way you expect is because of a bug in Karate 1.3.X - this is resolved in 1.4.0.RC3 - and you can find details here: https://github.com/karatelabs/karate/issues/2224

Peter Thomas
  • 54,465
  • 21
  • 84
  • 248