Search code examples
scalaspring-bootload-testinggatling

How to Integrate Gatling with existing Spring-Boot + Gradle application


I am trying to integrate Gatling to perform automation load testing. but I am getting different errors. I need some help on this topic.

I am using JDK-11 version

My Controller class as follows

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/health")
public class HealthController {

    private static final Logger LOGGER = LoggerFactory.getLogger(HealthController.class);
    
    @Autowired
    OptionRepository repository;
    
    @GetMapping("/{id}/options")
    public List<Health> findAllOptions(@PathVariable("id") Long id) {
        return (List<Health>) repository.findAll(id);
    }
    
    @GetMapping("/{id}/valid/dates")
    public List<Health> findByDates(@PathVariable("id") Long id) {
        return repository.findDates(id);
    }
    
}


@Data
class Health{
    List<String> options;
    List<String> dates;
}

My build.gradle as follows

/* ========================
 * Build
 * ========================
 */
buildscript {
    ext {
        springBootVersion = '2.4.4.RELEASE'
    }
    repositories {
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
        maven { url 'https://repo.spring.io/snapshot' }
        jcenter()
        
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.4.4")
        classpath "io.spring.gradle:dependency-management-plugin:0.6.1.RELEASE"

    }
}

/* ========================
 * Plugins
 * ========================
 */
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'jacoco'
apply plugin: 'scala'
apply plugin: 'java-library'

/* ========================
 * Project Info
 * ========================
 */
version = '1.0.0'

sourceCompatibility = 11
targetCompatibility = 11

defaultTasks 'bootRun'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}


/* ========================
 * Dependencies
 * =========================
 */
repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/snapshot' } 
}

configurations {
    providedRuntime
}

dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.16'
    annotationProcessor 'org.projectlombok:lombok:1.18.16'  
    testCompileOnly 'org.projectlombok:lombok:1.18.16'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'  
    compile('org.springframework.boot:spring-boot-starter-actuator')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile 'org.springframework.boot:spring-boot-starter-thymeleaf'    
    compile ('org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.4.4')
    compile('io.jsonwebtoken:jjwt:0.9.0')
    compile ('org.apache.commons:commons-csv:1.8')
    compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.3")
    compile 'org.apache.commons:commons-lang3:3.6'
    compile 'org.apache.commons:commons-collections4:4.0'
    runtime('org.springframework.boot:spring-boot-devtools')
    providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
    runtimeOnly('org.postgresql:postgresql:42.2.19')
    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('com.github.javafaker:javafaker:0.15')
    implementation ('org.mybatis.spring.boot:mybatis-spring-boot-test-autoconfigure:1.2.2')
    implementation ('org.liquibase:liquibase-core:4.3.2')
    implementation ('org.springdoc:springdoc-openapi-maven-plugin:1.2')
    implementation ('org.springdoc:springdoc-openapi-ui:1.5.5')
    implementation ('com.microsoft.sqlserver:mssql-jdbc:9.2.1.jre8')    
    
    //Tried with this libraries
    //compile 'org.scala-lang:scala-library:2.10.1'
    //implementation ('net.alchim31.maven:scala-maven-plugin:4.5.1')
    //implementation ('io.gatling:gatling-maven-plugin:3.1.2')
    testCompile('io.gatling.highcharts:gatling-charts-highcharts:2.3.0')
}

/* ========================
 * Task Configuration
 * ========================
 */
test {
    finalizedBy jacocoTestReport // report is always generated after tests run
    filter {
        excludeTestsMatching "com.dev.*"
    }
}

test.onlyIf { project.hasProperty('executeTests') }

jacoco {
    toolVersion = "0.8.6"
}

jacocoTestReport {
    reports {
        xml.enabled false
        csv.enabled false
        html.destination file("${buildDir}/reports/jacoco")
    }
    
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it,
                    exclude: ['**/domain/**'
                    ]
            )
        }))
    }
}

apply plugin: 'jacoco'
jacocoTestCoverageVerification {
  violationRules {
    rule {
      limit {
        minimum = 0.9
      }
    }
    rule {
            enabled = false
            element = 'CLASS'
            includes = ['org.gradle.*']

            limit {
                counter = 'LINE'
                value = 'TOTALCOUNT'
                maximum = 0.3
            }
        }
  }
}

/**
 * Gatling load tests
 */
task loadTest(type: JavaExec) {
   dependsOn testClasses
   description = "Load Test With Gatling"
   group = "Load Test"
   classpath = sourceSets.test.runtimeClasspath
   jvmArgs = [
        "-Dgatling.core.directory.binaries=${sourceSets.test.output.classesDirs.toString()}"
   ]
   main = "io.gatling.app.Gatling"
   args = [
           "--simulation", "com.dev.ApiGatlingSimulationTest",
           "--results-folder", "${buildDir}/gatling-results",
           //"--binaries-folder", sourceSets.test.output.classesDirs.toString(),
           "--bodies-folder", sourceSets.test.resources.srcDirs.toList().first().toString() + "/gatling/bodies",
   ]
}

def logbackGatlingConfig() {
    return sourceSets.test.resources.find { it.name == 'logback-gatling.xml' }
} 

bootJar { baseName = 'migroes-services' }

My scala test suit as follows

package com.dev
 
import io.gatling.core.scenario.Simulation
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import java.util.Date
import scala.concurrent.duration.FiniteDuration
import scala.concurrent.duration.Duration
import java.util.concurrent.TimeUnit

class ApiGatlingSimulationTest extends Simulation {

  val scn = scenario("Dev Status").repeat(1000, "n") {
        exec(
          http("Get All Options")
            .get("http://localhost:8080/health/dev-001/options")
            .check(status.is(200))
        ).pause(Duration.apply(5, TimeUnit.MILLISECONDS))    
  }.repeat(1000, "n") {
        exec(
          http("Valid Dates")
            .get("http://localhost:8090/health/dev-002/valid/dates")
            .check(status.is(200))
        )   
  }
  
  setUp(scn.inject(atOnceUsers(30))).maxDuration(FiniteDuration.apply(10, "minutes"))
  
}

Currently I am getting below error from Command line. I am first running the application via STS & then trying to fire gradle loadTest command.

D:\dev-repo\migroes-services>gradle clean build

> Task :compileJava
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

> Task :compileTestJava
Note: D:\dev-repo\migroes-services\src\test\java\com\dev\services\TestUtils.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.8.3/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 1m 3s
8 actionable tasks: 8 executed
D:\dev-repo\migroes-services>gradle loadTest

> Task :loadTest
21:02:53.898 [GatlingSystem-akka.actor.default-dispatcher-2] INFO akka.event.slf4j.Slf4jLogger - Slf4jLogger started
Exception in thread "main" io.gatling.core.session.el.ElParserException: Failed to parse VIN with error 'class [B cannot be cast to class [C ([B and [C are in module java.base of loader 'bootstrap')'
        at io.gatling.core.session.el.ElCompiler.parseEl(ElCompiler.scala:249)
        at io.gatling.core.session.el.ElCompiler$.parse(ElCompiler.scala:171)
        at io.gatling.core.session.el.ElCompiler$.compile(ElCompiler.scala:174)
        at io.gatling.core.session.el.package$El$.el$extension(package.scala:26)
        at io.gatling.core.ValidationImplicits.stringToExpression(ValidationImplicits.scala:48)
        at io.gatling.core.ValidationImplicits.stringToExpression$(ValidationImplicits.scala:48)
        at io.gatling.core.Predef$.stringToExpression(Predef.scala:22)
        at com.dev.ApiGatlingSimulationTest.<init>(ApiGatlingSimulationTest.scala:15)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
        at java.base/java.lang.Class.newInstance(Class.java:584)
        at io.gatling.app.Runner.run0(Runner.scala:79)
        at io.gatling.app.Runner.run(Runner.scala:64)
        at io.gatling.app.Gatling$.start(Gatling.scala:59)
        at io.gatling.app.Gatling$.fromArgs(Gatling.scala:43)
        at io.gatling.app.Gatling$.main(Gatling.scala:35)
        at io.gatling.app.Gatling.main(Gatling.scala)

> Task :loadTest FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':loadTest'.
> Process 'command 'C:\Program Files\Java\jdk-11.0.8\bin\java.exe'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.8.3/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 15s
6 actionable tasks: 1 executed, 5 up-to-date

I am getting most of time below error.

Exception in thread "main" io.gatling.core.session.el.ElParserException: Failed to parse VIN with error 'class [B cannot be cast to class [C ([B and [C are in module java.base of loader 'bootstrap')'

I tried to reach out several different blogs and similar situations on different platform. till now no luck !!


Solution

  •     testCompile('io.gatling.highcharts:gatling-charts-highcharts:2.3.0')
    
    

    You're trying to use Gatling 2 that has been dead for years. Please upgrade. Latest version is 3.5.1 as of now.