Tzatziki - Decathlon library to ease and promote Test Driven Development of Java microservices!

Related tags

Spring Boot tzatziki
Overview

Tzatziki Steps Library

Maven Central Build codecov License lifecycle: beta

This project is a collection of ready-to-use Cucumber steps making it easy to TDD Java microservices by focusing on an outside-in testing strategy.

Wait, Cucumber?

You are a Cucumber veteran? ... jump directly to Content of this project

Otherwise, here is what wikipedia says:

Cucumber is a software tool used by computer programmers for testing other software. It runs automated acceptance tests written in a behavior-driven development (BDD) style. Central to the Cucumber BDD approach is its plain language parser called Gherkin. It allows expected software behaviors to be specified in a logical language that customers can understand. As such, Cucumber allows the execution of feature documentation written in business-facing text.

What does it mean to us developers?

Cucumber provides a mapping between humanly readable test files written in a language called Gherkin and their JUnit implementations. You can think about it as a partition that will execute pieces of JUnit code.

Why using Cucumber?

By creating a separation between a test expression and its implementation, the resulting Cucumber test tends to be a bit more readable than its JUnit counterpart. Additionaly, the reusability of each JUnit implementation is really high, and over time only the Gherkin needs to be added to test a new feature.

Okay ... so how does it work?

Getting started with Cucumber in 5 mins

The Cucumber tests are written in .feature files. Most of the IDEs have support for writting, running and debugging cucumber tests. Since deep down they are just JUnit tests, once they are running everything should be the same: code coverage, reporting etc.

The structure of a .feature file is the following:

Feature: the name of your feature
  Here you can put some comments describing your feature

  Background: some stuff that needs to be done for every scenario
    * a system is running

  @this-is-a-tag
  Scenario: Change a state in the system
  As a User I expect to go from A to C if B happens

    Given a state A
    When B happens
    # we can also put comments if things need a bit of explanation
    Then C is the new state of the system

  Scenario: some other scenario
  ...

The lines starting with Given, When, Then are called Steps. Additional Steps keywords are And and But (* is also accepted). Those keywords don't really have a functional meaning, they are just there for us to write nice tests. We could start every step with * and the output of the test would be exactly the same. However, you should choose the one fitting the most the intent of the step you are writing. A big part of the idea behind using Gherkin, is that the tests are the specifications of the code, so it should be enough to read them to understand the product they test.

An optional Background section can be added at the beginning. The steps in it will be repeated before any scenario in the file, like a method annotated with @org.junit.Before.

Each Step has an implementation in plain Java that is annotated with a regular expression matching the step.

So for example:

Given that we do something

will have the following implementation:

@Given("that we do something")
public void do_something(){
  // do something here
}

Cucumber can extract parameters directly from a step so that:

Given a user named "bob"

can be implemented as:

@Given("a user named \"(.*)\"")
public void a_user_named(String name){
  // create a user with that name
}

But it also supports multiline arguments:

Given the following configuration file:
  """
  property: value
  """
@Given("the following configuration file:")
public void the_following_configuration_file(String content){
  // do something with the file content
}

as well as tables:

Given the following users:
  | id  | name    |
  | 1   | bob     |
  | 2   | alice   |
@Given("the following users")
public void the_following_users(List<Map<String, String>> users){
  // do something with those users
}

Those Java methods need to be added to a Steps class, typically something like LocalSteps. Keep in mind that for technical reasons Cucumber will not allow you to extend those steps. Instead, the framework will enforce composition, and if any class extending a Steps class is detected, an exception will be thrown.

Cucumber also comes with support for injection frameworks, so all your dependencies will be properly instantiated and injected at runtime, per scenario.

Note that your @org.junit.Before and @org.junit.After annotations won't work in your steps. You need to use the Cucumber equivalent: @cucumber.api.java.Before and @cucumber.api.java.After

Example:

public class BaseSteps {

    @Before
    public void before() {
        // something to run before each scenario
    }

    @Given("that we do something")
    public void do_something(){
      // do something here
    }
}

public class LocalSteps {

    private final BaseSteps baseSteps;

    public LocalSteps(BaseSteps baseSteps) {
        this.baseSteps = baseSteps;
    }

    @Given("a user named \"(.*)\"")
    public void a_user_named(String name){
        baseSteps.do_something();  
        // create a user with that name
    }

    @Given("the following users")
    public void the_following_users(List<Map<String, String>> users){
        // do something with those users
    }

    @After
    public void after() {
        // something to run after each scenario
    }
}

Finally, in order to have JUnit execute our Cucumber tests we need a runner:

package com.yourcompany.yourproject;

import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(plugin = "pretty")
public class CucumberTest {}

By default, cucumber will look for .feature files in the same directory structure than the java runner. However, this can be configured using the features property on the @io.cucumber.junit.CucumberOptions annotation. In addition, it will also look for Java classes containing steps next to the runner and this can also be configured by using the glues property on the same annotation.

Tip: Sometimes it can be hard to come up with the implementation steps... but if you start by typing your new step in your feature file and then execute the scenario, Cucumber will output an implementation for you:

  Undefined step: Given something else that is not yet implemented

  Skipped step

  Skipped step

  Skipped step

  1 Scenarios (1 undefined)
  5 Steps (3 skipped, 1 undefined, 1 passed)
  0m0.250s


  You can implement missing steps with the snippets below:

  @Given("^something else that is not yet implemented")
  public void something_else_that_is_not_yet_implemented() throws Throwable {
      // Write code here that turns the phrase above into concrete actions
      throw new PendingException();
  }

Content of this project

This repository contains several libraries, each one having its own tutorial and documentation when applicable:

  • tzatziki-common : dependency module containing the base classes for the core library, but without cucumber.
  • tzatziki-core : the core library, provides support of our test instances as well as input/output and time management.
  • tzatziki-logback : the logging library, provides support for dynamically configuring the log levels in your tests.
  • mockfaster : static wrapper around mockserver to reduce the time taken by redefining mocks.
  • tzatziki-http : http library encapsulating both rest-assured and mockserver.
  • tzatziki-spring : base library to start a spring service
  • tzatziki-spring-jpa : support for spring jpa to insert and assert data in the database.
  • tzatziki-spring-kafka : support for spring kafka listener and consumers.

Support

We welcome contributions, opinions, bug reports and feature requests!

Comments
  • fix: contains exactly comparison pattern

    fix: contains exactly comparison pattern

    Comparison pattern contains? exactly from https://github.com/Decathlon/tzatziki/blob/5cae3967c28c744e37b03c95d252f37dd0908c47/tzatziki-common/src/main/java/com/decathlon/tzatziki/utils/Comparison.java#L16 is not a known title amongst the Comparison enum members. It is therefore by default parsed as the pattern contains?. I don't think it should and should be treated as the exactly pattern.

    Warning

    this change presents a slight breaking change that could affect some users that would have used this pattern instead of the more permissive contains

    opened by z06lsouc 14
  • feat: extract data from repository

    feat: extract data from repository

    When inserting data into tables where ids are auto generated and that I needed to link, I found no way of getting the value that was actually inserted in the DB. Either for testing DB triggers or low level transformations, I believe fetching data from the repositories is a common enough need to add this PR to the library. It simply does a findAll and store the content in a var. It follows ObjectSteps and SpringJPASteps naming conventions as close as possible.

    opened by z06lsouc 10
  • bug:

    bug: "after \\d+ms|" checks are not always done.

    It seems that guard which contain "after Xms" are not check. It seems that when using this keyword, the check are done in async, by using another thread from the main one. I suppose that as the main thread is over before the Xms duration, then the "sub threads" are over too, and so the checks are not done.

    unnamed

    PS: Maybe we should have some "labels" available in order to organize the issues?

    documentation 
    opened by ThomasCaud 9
  • [tzatziki-logback] the log contains: ConcurrentModificationException

    [tzatziki-logback] the log contains: ConcurrentModificationException

    ConcurrentModificationException while checking the logs:

    java.util.ConcurrentModificationException
    	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1631)
    	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
    	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    	at org.assertj.core.internal.Iterables.satisfiesCondition(Iterables.java:1384)
    	at org.assertj.core.internal.Iterables.conditionIsSatisfiedAtLeastNTimes(Iterables.java:953)
    	at org.assertj.core.internal.Iterables.assertAreAtLeast(Iterables.java:944)
    	at org.assertj.core.api.AbstractIterableAssert.areAtLeast(AbstractIterableAssert.java:727)
    	at com.decathlon.tzatziki.steps.LoggerSteps.lambda$the_logs_contain$7(LoggerSteps.java:142)
    	at com.decathlon.tzatziki.steps.LoggerSteps.lambda$the_logs_contain$12(LoggerSteps.java:147)
    	at com.decathlon.tzatziki.utils.Guard.in(Guard.java:50)
    	at com.decathlon.tzatziki.utils.Guard$5.lambda$in$0(Guard.java:191)
    	at org.awaitility.core.AssertionCondition.lambda$new$0(AssertionCondition.java:53)
    	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:248)
    	at org.awaitility.core.ConditionAwaiter$ConditionPoller.call(ConditionAwaiter.java:235)
    	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    	at java.base/java.lang.Thread.run(Thread.java:833)
    	at ?.within 10000ms the logs contains at least 3 lines equal to "?contains {{expectedLog}}"
    

    AssertJ directly delegates any list assertion to java stream with filtering, therefore any concurrent modification of the list is not allowed. I've probably run into this because I'm testing a background process that will continue to log; thus logs may be added to the ListAppender while checking said appender if the test pipeline slows down enough.

    Unfortunately the ListAppender comes from another lib (Semla) and uses internally an ArrayList which does not provide any thread safe way to iterate over it (either for direct check or copy).

    opened by z06lsouc 8
  • Exclude the commons-text dependency

    Exclude the commons-text dependency

    A vulnerability 9.8/10 has been detected on the commons-text 1.9.0 library

    Correction :

    • Exclude it
    • Uprgarde to the 1.10.0 version

    https://commons.apache.org/proper/commons-text/security.html

    ** Note ** : this dependency is used by mockserver and in its new version 5.14.0, it still uses the vulnerable library

    opened by mamdouni 6
  • [tzatziki-spring] Multiple bean found when launching scenario for a WebFlux application

    [tzatziki-spring] Multiple bean found when launching scenario for a WebFlux application

    Disclaimer

    I am not sure whether the following issue is specific to my existing project. I did not try bootstrapping an empty WebFlux project to try Tzatziki, but I should be able to try later.

    Context

    POM

    We are using a multimodule project with following parent:

      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.1</version>
      </parent>
    

    and on the child module (api) containing launcher:

    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-webflux</artifactId>
          <!-- See CVE https://cve.report/CVE-2021-44228 -->
          <exclusions>
            <exclusion>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-api</artifactId>
            </exclusion>
            <exclusion>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-to-slf4j</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
    

    Java

    Java version is the following:

    openjdk version "17" 2021-09-14
    OpenJDK Runtime Environment (build 17+35-2724)
    OpenJDK 64-Bit Server VM (build 17+35-2724, mixed mode, sharing)
    

    Files

    POM

    In my api POM, I added:

        <dependency>
          <groupId>com.decathlon.tzatziki</groupId>
          <artifactId>tzatziki-spring</artifactId>
          <version>1.0.1</version>
          <scope>test</scope>
        </dependency>
    

    Production code

    package com.company.package;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Api {
    
      public static void main(String[] args) {
        SpringApplication.run(Api.class, args);
      }
    
    }
    
    

    Steps file

    I then added the following file in test source folder:

    package com.company.package.cumcumber;
    
    import com.company.package.Api;
    import io.cucumber.spring.CucumberContextConfiguration;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
    import org.springframework.boot.web.reactive.context.ConfigurableReactiveWebApplicationContext;
    import org.springframework.context.ApplicationContextInitializer;
    import org.springframework.test.context.ContextConfiguration;
    
    @CucumberContextConfiguration
    @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = Api.class)
    @ContextConfiguration(initializers = ApiSteps.Initializer.class)
    public class ApiSteps {
    
      static class Initializer implements ApplicationContextInitializer<ConfigurableReactiveWebApplicationContext> {
    
        public void initialize(ConfigurableReactiveWebApplicationContext configurableApplicationContext) {
    
        }
      }
    
    }
    
    

    Note: I also tried to switch to org.springframework.context.ConfigurableApplicationContext, with the same result.

    Along with the feature file in test resources folder:

    Feature: a polite spring boot service
    
      Scenario: our service can greet us
        When we call "/hello"
        Then we receive "Hello world!"
    

    Error

    Running the test directly through IntelliJ (I can send you complete command line ran by IntelliJ if required), I encounter the following error:

    Before All/After All failed
    java.lang.IllegalStateException: Failed to load ApplicationContext
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
    	at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
    	at io.cucumber.spring.TestContextAdaptor.createTestContextManagerAdaptor(TestContextAdaptor.java:40)
    	at io.cucumber.spring.SpringFactory.start(SpringFactory.java:154)
    	at io.cucumber.core.runner.Runner.buildBackendWorlds(Runner.java:134)
    	at io.cucumber.core.runner.Runner.runPickle(Runner.java:70)
    	at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
    	at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:110)
    	at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
    	at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:110)
    	at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
    	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    	at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
    	at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:123)
    	at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
    	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
    	at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:200)
    	at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1602)
    	at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129)
    	at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527)
    	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513)
    	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
    	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
    	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
    	at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
    	at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
    	at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
    	at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
    	at io.cucumber.core.cli.Main.run(Main.java:87)
    	at io.cucumber.core.cli.Main.main(Main.java:30)
    Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'errorAttributes' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/error/ErrorMvcAutoConfiguration.class]] for bean 'errorAttributes': There is already [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration; factoryMethodName=errorAttributes; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/error/ErrorWebFluxAutoConfiguration.class]] bound.
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:995)
    	at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:295)
    	at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:153)
    	at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129)
    	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343)
    	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
    	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
    	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
    	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
    	at org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh(ReactiveWebServerApplicationContext.java:64)
    	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
    	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412)
    	at org.springframework.boot.SpringApplication.run(SpringApplication.java:302)
    	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:121)
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
    	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    	... 31 more
    

    Idea

    Reading your code, it seems like everything should work, so my guess is either:

    • Cucumber runners is not compatible with WebFlux or requires a tweak
    • I have some conflicts in my project setup
    opened by hypr2771 6
  • using tzatziki with Oracle (part 2)

    using tzatziki with Oracle (part 2)

    Hello,

    thanks for your work on the issue #56. Now we can go a little bit further ! But there are still sql scripts in hard that are not compatible with Oracle. Now, it is this one that makes the test crash at the initializing phase : com.decathlon.tzatziki.steps.SpringJPASteps l.154 image The error : bad SQL grammar [TRUNCATE xxxxx RESTART IDENTITY CASCADE]; nested exception is java.sql.SQLSyntaxErrorException: ORA-03290: Commande de troncation erronée - mot-clé CLUSTER ou TABLE absent

    Thank you again for your help. Best regards. Sylvain G.

    opened by z05sgoul 3
  • using tzatziki with Oracle

    using tzatziki with Oracle

    Hello, I am using Tzatziki for our tests. Recently, following a typing problem, we had to align our test database with the real one... Unfortunately, with an Oracle database, we encounter errors when initiating our data with step : that the [table] table will contain only: error : org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [select tablename from pg_catalog.pg_tables where schemaname='public']; nested exception is java.sql.SQLSyntaxErrorException: ORA-00942: Non-existent table or view.

    Thank you for your work Best regards, Sylvain G.

    opened by z05sgoul 3
  • Some variable names can break the lib

    Some variable names can break the lib

    Hello,

    When updating to 1.0.8, an error occurred in some old tests concerning the connection to the application during http calls.

    When MYUSER posts on "/myapi"...
    
    java.lang.AssertionError: Connection refused
    Caused by: java.net.ConnectException: Connection refused
    

    It appears to be caused by a variable initialized at the start of the feature, with the name "local", which was overriding the "local.port" variable used by the lib to retrieve the spring application port.

      Background: Init variables
        * local is "AT"
    

    To fix this I renamed it to locale, but I guess it can be managed differently in the lib ? I also guess it's not the only name that can cause this kind of problems.

    opened by hqrd 3
  • fix: Use of TypeUtils to fix getRepositoryForEntity method

    fix: Use of TypeUtils to fix getRepositoryForEntity method

    Currently, while using the sentence like "that the DeliveryEventEntity entities will contain:", we get the following error: Capture d’écran 2022-01-24 à 16 32 09

    I fixed that the same way than getRepositoryForTable works, filtering on our CrudRepository classes. It now works on my local env.

    opened by ThomasCaud 3
  • use computeIfAbsent to set the default consumers

    use computeIfAbsent to set the default consumers

    I think that maybe using computeIfAbsent leads to a nicer result, what do you think?

    (I also removed the split on | ... this is very specific to your inBounds example and can as well be done in the consumer)

    opened by mimfgg 2
  • [tzatziki-http] Allow specific unhandled requests

    [tzatziki-http] Allow specific unhandled requests

    Context

    Right now by default if you want to disable checking for unhandled requests, you must use the we allow unhandled mocked requests statement in scenarios. ~Even this mechanism is not clear, looking at the code I'm not sure if the statement is only scoped to the scenario it is declared in. Are step classes re-instantiated for each scenario ? If not, the behavior may affect others and make the whole mechanism susceptible to the scenarios' order of execution.~ A~nyway, the point is, a~s of this issue, safety can only be turned off globally.

    In my case I'm using a Camunda external task client that frequently checks with a server to execute tasks. I cannot turn it off nor would I want it since it is the main way to actually test the tasks that I develop. I just need Tzatziki to allow unhandled requests on the endpoint that the framework calls.

    Request

    Allow only specific unhandled requests, either through :

    • a gherkin statement: The effect would apply only to the current scenario. The statement could look like: we allow unhandled mocked requests getting on "/some/endpoint".
    • java static methods: The effect would apply to the entire lifespan of Tzatziki. It would require methods to add and remove requests from the configuration. This option suits me better but I understand that modifying the entire lifespan of Tzatziki could be too much.

    When it comes to matching unhandled requests, maybe we could have more complex input allowing for Interaction object such as to be uniform with the assertions provided by HttpSteps.

    opened by z06lsouc 0
  • [tzatziki-http] Invalid regex throwing PatternSyntaxException in callback function for interaction and is not caught

    [tzatziki-http] Invalid regex throwing PatternSyntaxException in callback function for interaction and is not caught

    When creating a mock for an Interaction, if the url string is an invalid regex, compiling it will throw a PatternSyntaxException which will only be caught by MockServer which defaults to a 404 instead of the return status and body from the Given step.

    Error occurs in HttpSteps: https://github.com/Decathlon/tzatziki/blob/45876446663d2e7ea420f316c70fc9d328747d88/tzatziki-http/src/main/java/com/decathlon/tzatziki/steps/HttpSteps.java#L163

    For example:

    Given that getting on "/products?search[]=123" will return a status OK_200 and:
    """
    product:
      id:1
    """
    

    When my application then makes a call to "/products?search[]=123", the callback function throws an error which is caught by Mockserver:

    2022-12-06 20:08:51,276 [WARN ] [MockServer-EventLog0] o.m.l.MockServerEventLog - 59964 returning { "statusCode" : 404, "reasonPhrase" : "Not Found" } because client 6a591f01-8d7d-491a-b4df-2e907b24fef7 response callback throw an exception java.util.regex.PatternSyntaxException: Unclosed character class near index 21 /products?search[]=123 ^

    This is caused due to the empty square brackets [] which will cause Pattern.compile to throw the exception

    Proposed solution:

    Only compile the mocked url to a regex if it is one, or if the return body is a template ( with $1 $2 etc ... )

    This whole block can also be skipped (?) if the url and return body are literals string https://github.com/Decathlon/tzatziki/blob/45876446663d2e7ea420f316c70fc9d328747d88/tzatziki-http/src/main/java/com/decathlon/tzatziki/steps/HttpSteps.java#L186-L204

    opened by rbarronDecathlon 3
  • chore(deps-dev): bump postgresql from 42.3.3 to 42.3.8 in /tzatziki-spring-jpa

    chore(deps-dev): bump postgresql from 42.3.3 to 42.3.8 in /tzatziki-spring-jpa

    Bumps postgresql from 42.3.3 to 42.3.8.

    Changelog

    Sourced from postgresql's changelog.

    Changelog

    Notable changes since version 42.0.0, read the complete History of Changes.

    The format is based on Keep a Changelog.

    [Unreleased]

    Changed

    Added

    Fixed

    [42.5.1] (2022-11-21 15:21:59 -0500)

    Security

    • security: StreamWrapper spills to disk if setText, or setBytea sends very large Strings or arrays to the server. createTempFile creates a file which can be read by other users on unix like systems (Not macos). This has been fixed in this version fixes CVE-2022-41946 see the security advisory for more details. Reported by Jonathan Leitschuh This has been fixed in versions 42.5.1, 42.4.3 42.3.8, 42.2.27.jre7. Note there is no fix for 42.2.26.jre6. See the security advisory for work arounds.

    Fixed

    [42.5.0] (2022-08-23 11:20:11 -0400)

    Changed

    [42.4.2] (2022-08-17 10:33:40 -0400)

    Changed

    • fix: add alias to the generated getUDT() query for clarity (PR #2553)[https://github-redirect.dependabot.com/pgjdbc/pgjdbc/pull/2553]

    Added

    Fixed

    • fix: regression with GSS. Changes introduced to support building with Java 17 caused failures [Issue #2588](pgjdbc/pgjdbc#2588)
    • fix: set a timeout to get the return from requesting SSL upgrade. [PR #2572](pgjdbc/pgjdbc#2572)
    • feat: synchronize statement executions (e.g. avoid deadlock when Connection.isValid is executed from concurrent threads)

    [42.4.1] (2022-08-01 16:24:20 -0400)

    Security

    • fix: CVE-2022-31197 Fixes SQL generated in PgResultSet.refresh() to escape column identifiers so as to prevent SQL injection.
      • Previously, the column names for both key and data columns in the table were copied as-is into the generated SQL. This allowed a malicious table with column names that include statement terminator to be parsed and executed as multiple separate commands.
      • Also adds a new test class ResultSetRefreshTest to verify this change.
      • Reported by Sho Kato

    ... (truncated)

    Commits
    • e73c6b6 backpatch changes to 42.3.x for 42.5.1 (#2674)
    • 3ea7e61 bumped version for next release
    • 0afaa71 backpatch changes from GHSA-r38f-c4h4-hqq2 security advisory for CVE-2022-311...
    • 7714d03 Created release notes for 42.3.6 [SKIP-CI] (#2515)
    • 85f8581 fix: close refcursors when underlying cursor==null instead of relying on defa...
    • 12541c4 bumped version number
    • 0872ad0 Fix heading format for version numbers (#2504)
    • 0d6ccb1 More changlog additions added chore to terminate CI jobs on fast PR pushes [S...
    • 2bd774e Releasenotes 42.3.5 (#2502)
    • c04582e chore: use GitHub Action concurrency feature to terminate CI jobs on fast PR ...
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • [tzatziki-spring] Spring-Web dependencies are transitive

    [tzatziki-spring] Spring-Web dependencies are transitive

    It leads to a classpath poisoning since an application would behave differently based on the dependency presence or not in the production classpath.

    Set those dependencies to provided and eventually handle the @LocalServerPort differently with a ServerPortFactory which would only load the property @ConditionalOnWebApplication

    opened by brian-mulier 0
  • [tzatziki-spring] HttpInterceptor is not agnostic of the classpath dependencies

    [tzatziki-spring] HttpInterceptor is not agnostic of the classpath dependencies

    Since interceptions on multiple component which come from several distinct dependencies (reactive for eg.), if we put those dependencies as provided (to prevent classpath poisoning in tests while not in production), it would result in a compilation error in case of a missing dependency (which will probably be the case).

    Perhaps a solution would be to get a List which would be populated conditionally on class to check if the client is in the classpath then ran.

    opened by brian-mulier 0
Releases(v1.2.21)
  • v1.2.21(Dec 30, 2022)

    What's Changed

    • ft : Can now create custom flags for assertions by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/128

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.20...v1.2.21

    Source code(tar.gz)
    Source code(zip)
  • v1.2.20(Dec 23, 2022)

    What's Changed

    • Fx/call method split by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/126

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.19...v1.2.20

    Source code(tar.gz)
    Source code(zip)
  • v1.2.19(Dec 22, 2022)

    What's Changed

    • feat: noIndent helper by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/125

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.18...v1.2.19

    Source code(tar.gz)
    Source code(zip)
  • v1.2.18(Dec 13, 2022)

    What's Changed

    • fix(issue #119): Escape empty brackets [] when present in query parameters by @rbarronDecathlon in https://github.com/Decathlon/tzatziki/pull/121

    New Contributors

    • @rbarronDecathlon made their first contribution in https://github.com/Decathlon/tzatziki/pull/121

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.17...v1.2.18

    Source code(tar.gz)
    Source code(zip)
  • v1.2.17(Dec 13, 2022)

    What's Changed

    • fix: consider NOT_FOUND after reset callbacks as unhandled request by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/124

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.16...v1.2.17

    Source code(tar.gz)
    Source code(zip)
  • v1.2.16(Dec 11, 2022)

    What's Changed

    • fix: dynamic file name for file loading and bug on timestamp detected… by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/123

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.15...v1.2.16

    Source code(tar.gz)
    Source code(zip)
  • v1.2.15(Dec 8, 2022)

    What's Changed

    • Fix consumer c'an't consume records by @ibrahimhammanid in https://github.com/Decathlon/tzatziki/pull/118
    • fix: http mock redefinitions always working by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/122

    New Contributors

    • @ibrahimhammanid made their first contribution in https://github.com/Decathlon/tzatziki/pull/118

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.14...v1.2.15

    Source code(tar.gz)
    Source code(zip)
  • v1.2.14(Nov 29, 2022)

    What's Changed

    • feat: properly handling repository inheritance (with specific-to-gene… by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/116

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.13...v1.2.14

    Source code(tar.gz)
    Source code(zip)
  • v1.2.13(Nov 29, 2022)

    What's Changed

    • fix: Jackson YAML mapper no longer add new lines by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/117

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.12...v1.2.13

    Source code(tar.gz)
    Source code(zip)
  • v1.2.12(Nov 22, 2022)

    What's Changed

    • fix: XML now treated as raw String in HttpSteps by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/114

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.11...v1.2.12

    Source code(tar.gz)
    Source code(zip)
  • v1.2.11(Nov 22, 2022)

    What's Changed

    • Bump the commons-text dependency to fix security issue by @mamdouni in https://github.com/Decathlon/tzatziki/pull/103

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.10...v1.2.11

    Source code(tar.gz)
    Source code(zip)
  • v1.2.10(Nov 22, 2022)

    What's Changed

    • Ft/better dot notation by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/113

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.9...v1.2.10

    Source code(tar.gz)
    Source code(zip)
  • v1.2.9(Nov 21, 2022)

    What's Changed

    • Ft/better dot notation by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/112

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.8...v1.2.9

    Source code(tar.gz)
    Source code(zip)
  • v1.2.8(Nov 21, 2022)

    What's Changed

    • fix: jpa working again with external libraries (since entities are no… by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/111

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.7...v1.2.8

    Source code(tar.gz)
    Source code(zip)
  • v1.2.7(Nov 17, 2022)

    What's Changed

    • feat: nested object or list can also be set with dot notation by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/110

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.6...v1.2.7

    Source code(tar.gz)
    Source code(zip)
  • v1.2.6(Nov 16, 2022)

    What's Changed

    • fix: no more NPE when no entityManagerFactories by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/109

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.5...v1.2.6

    Source code(tar.gz)
    Source code(zip)
  • v1.2.5(Nov 15, 2022)

    What's Changed

    • feat: working entity inheritance by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/108

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.4...v1.2.5

    Source code(tar.gz)
    Source code(zip)
  • v1.2.4(Nov 14, 2022)

    What's Changed

    • fix: log assertions concurrent modification by @z06lsouc in https://github.com/Decathlon/tzatziki/pull/107

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.3...v1.2.4

    Source code(tar.gz)
    Source code(zip)
  • v1.2.3(Oct 28, 2022)

    What's Changed

    • fix: bug on multi-conditional guards by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/104
    • Fx/multi conditional guard by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/105

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.2...v1.2.3

    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Oct 18, 2022)

    What's Changed

    • fix: working empty string matched against a map when comparing list e… by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/101
    • Ft/optional dot notation to object by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/102

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.1...v1.2.2

    Source code(tar.gz)
    Source code(zip)
  • v1.2.1(Oct 14, 2022)

    What's Changed

    • feat: single nested field can be set through dot notation by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/98

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.2.0...v1.2.1

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 5, 2022)

    What's Changed

    • fix: now properly asserting fields which have default value by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/90

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.1.3...v1.2.0

    Source code(tar.gz)
    Source code(zip)
  • v1.1.3(Oct 5, 2022)

    What's Changed

    • feat: can now get application bean through context variable by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/97

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.1.2...v1.1.3

    Source code(tar.gz)
    Source code(zip)
  • v1.1.2(Sep 27, 2022)

    What's Changed

    • fix: avoid NullPointerException in getRepositoryForTable if there is repositories with inheritance in the application by @hqrd in https://github.com/Decathlon/tzatziki/pull/95

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.1.1...v1.1.2

    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Sep 27, 2022)

    What's Changed

    • feat: we can now call any method with(out) parameters using step or inline assignment by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/91

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.1.0...v1.1.1

    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Sep 27, 2022)

    What's Changed

    • feat: add log count assertion by @z06lsouc in https://github.com/Decathlon/tzatziki/pull/93
    • fix: spring cache comparison syntax and add comparison variations by @z06lsouc in https://github.com/Decathlon/tzatziki/pull/94

    Breaking changes:

    • The comparison done in assertion step "the cache contains" is now a parameter. However, the previous behaviour was to do an "is exactly" comparison while the step had an hard-coded "contains" keyword in it, resulting in confusions. ==> If you are using this step, you should replace all your "the cache contains" steps in your features with "the cache is exactly", else it could result in a false positive where your cache contains more than just what is asserted while it used to be strict.

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.0.50...v1.0.51

    Source code(tar.gz)
    Source code(zip)
  • v1.0.50(Sep 14, 2022)

    What's Changed

    • docs: Update README.md by @ThomasCaud in https://github.com/Decathlon/tzatziki/pull/86
    • chore: bump kafka-avro-serializer to v7.2.1 by @guillaume-fbz in https://github.com/Decathlon/tzatziki/pull/87

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.0.49...v1.0.50

    Source code(tar.gz)
    Source code(zip)
  • v1.0.49(Aug 11, 2022)

    What's Changed

    • fix: urls are now case-sensitive by @brian-mulier in https://github.com/Decathlon/tzatziki/pull/85

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.0.48...v1.0.49

    Source code(tar.gz)
    Source code(zip)
  • v1.0.48(Jul 28, 2022)

  • v1.0.47(Jul 25, 2022)

    What's Changed

    • feat: Database usage - close ResultSet by @z05sgoul in https://github.com/Decathlon/tzatziki/pull/82

    New Contributors

    • @z05sgoul made their first contribution in https://github.com/Decathlon/tzatziki/pull/82

    Full Changelog: https://github.com/Decathlon/tzatziki/compare/v1.0.46...v1.0.47

    Source code(tar.gz)
    Source code(zip)
Owner
Decathlon
Decathlon
Java library to perform reverse Domain Name Service (rDNS) lookups with ease.

ipregistry-rdns Java library to perform reverse Domain Name Service (rDNS) lookups with ease. The library is async, thread-safe and has built-in suppo

Ipregistry 2 Jul 18, 2022
Community-Driven Game Server Development solution for Java Developers based on DEEPINTHINK MagOKO Project.

MagOKO Stack Community-Driven Game Server Development solution for Java Developers based on DEEPINTHINK MagOKO Project. License Copyright 2021-present

DeepInThink Community 10 Jun 1, 2021
Test-Driven Security

Test-Driven Security Run tests ./gradlew test References Spring Security test support https://docs.spring.io/spring-security/site/docs/current/referen

Eleftheria Stein-Kousathana 60 Oct 11, 2022
Auto-Unit-Test-Case-Generator automatically generates high-level code-coverage JUnit test suites for Java, widely used within the ANT Group.

中文README传送门 What is Auto-Unit-Test-Case-Generator Auto-Unit-Test-Case-Generator generates JUnit test suites for Java class just as its name. During te

TRaaS 108 Dec 22, 2022
A base repo for creating RPC microservices in Java with gRPC, jOOQ, and Maven.

Wenower Core OSX local installation Install Protocol Buffer $ brew install protobuf Install Postgresql and joopc database and user $ brew install pos

Hamidreza Soleimani 1 Jan 9, 2022
Spring Domain Driven Design Boilerplate

Spring Domain Driven Design Boilerplate This project describes some product operations such as create and get, also covered by Domain Driven Design on

Dolap.com Development Team 40 Dec 29, 2022
Joyce is a highly scalable event-driven Cloud Native Data Hub.

Joyce Component docker latest version Build Import Gateway sourcesense/joyce-import-gateway Joyce Kafka Connect sourcesense/joyce-kafka-connect Mongod

Sourcesense 37 Oct 6, 2022
Application for creating blog posts, developed with Java using Spring Framework for backend and Angular along with PrimeNG Library for frontend development.

Application for creating blog posts, developed with Java using Spring Framework for backend and Angular along with PrimeNG Library for frontend development.

Áureo Carmelino 10 Nov 27, 2022
Spring Boot microservices app with Spring Cloud, Robust and resilient backend managing e-Commerce app

e-Commerce-boot μServices Important Note: This project's new milestone is to move The whole system to work on Kubernetes, so stay tuned. Introduction

Selim Horri 65 Dec 23, 2022
A boilerplate project designed to work as a template for new microservices and help you get in touch with various useful concepts.

Microservice Reference Project This project is inspired by the idea to quickly create a production ready project with all the required infrastructure

Innovation & Tech 4 Dec 17, 2022
A fast, lightweight and more productive microservices framework

A fast, lightweight and cloud-native microservices framework. Stack Overflow | Google Group | Gitter Chat | Subreddit | Youtube Channel | Documentatio

null 3.5k Jan 5, 2023
Microservices with Spring Boot and Kafka Demo Project

Example microservices showing how to use Kafka and Kafka Streams with Spring Boot on the example of distributed transactions implementations with the SAGA pattern

Piotr Mińkowski 98 Jan 7, 2023
Example project of Spring Boot Microservices with the following services School and Student

SpringBootMicroservicesWithDiscoveryGatewayConfig Example project of Spring Boot Microservices with the following services School and Student, additio

Gábor Hutya 2 Nov 28, 2022
A fast, light and cloud native OAuth 2.0 authorization microservices based on light-4j

A fast, light weight and cloud native OAuth 2.0 Server based on microservices architecture built on top of light-4j and light-rest-4j frameworks. Stac

null 291 Dec 17, 2022
Saga pattern with Java => order -> payment -> stock microservices are ready to use

Order_Payment_Stock_Saga_Pattern Saga pattern with Java => order -> payment -> stock microservices are ready to use Docker-compose.yaml You can see th

Gurkan İlleez 5 Dec 27, 2022
Java libraries for writing composable microservices

Apollo Status: Archived ⚠️ Apollo is heavily used within Spotify, however, most of its development has recently been done internally leveraging Apollo

Spotify 1.6k Dec 6, 2022
Trust-java - Test Results Verification library for Java

TRUST - Test Results Verification library for Java The TRUST's primary goal is to provide the simple way of different test results verification. Gener

Serhii Shymkiv 2 Nov 19, 2017
A lightweight messaging library that simplifies the development and usage of RabbitMQ with the AMQP protocol.

kryo-messaging This library contains a simple MessagingService which simplifies the setup and work with RabbitMQ and the AMQP protocol. Usage Gradle r

Kryonite Labs 3 Jan 10, 2022
Nrich is a Java library developed at CROZ whose purpose is to make development of applications on JVM a little easier.

nrich Nrich is a Java library developed at CROZ whose purpose is to make development of applications on JVM a little easier. It contains modules that

CROZ 44 Nov 12, 2022