gauge icon indicating copy to clipboard operation
gauge copied to clipboard

How to run Spring Boot and Spring Data with Gauge framework

Open AhmetRufai opened this issue 4 years ago • 9 comments

Is your feature request related to a problem? Please describe. Yes, Spring Boot project on Gauge does not work. I'm trying to injection with @Autowired annotation but the injection is not happening. Throwing NullPointerException error.

Describe the solution you'd like When I run the method for db query with Junit, it runs successfully. I specify the annotations below in the class where the method is located. I could not find a similar solution for Gauge.

import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class)

Note: Application class is the main class of my project that enables Spring to run.

Describe alternatives you've considered They developed a solution for this situation in the Cucumber framework. A similar solution can be provided. If we cannot solve this problem, unfortunately, we will have to stop using Gauge.

Additional context Hi, In a large e-commerce company in Turkey, test automation structure, we decided to create using the Gauge Framework. We have created a project structure with spring boot and spring data for our DB connections and queries on the Java side. The Spring infrastructure we have created works successfully when run from the java main class. But when we want to run it with the Gauge runner, Spring does not stand up. Do you have a solution for this situation?

Project structure:

  • spec
    • Payment.spec
  • src
    • main
      • java
        • model
          • PaymentEntity.java
        • repository
          • PaymentRepository.java(this class is an interface and extends CrudRepository.java)
        • service
          • PaymentService.java
        • Application.java(main class)
      • resources
        • application.properties
    • test
      • java
        • payment
          • DbCheck.java (I want to perform a db query in this class)
        • step
          • PaymentStep.java (extends DbCheck.java)

Content of the DbCheck Class:

package payment;

import Application;
import model.PaymentEntity;
import service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;

@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class DbCheck {

    @Autowired
    private PaymentService paymentService;

    @Test
    public void checkData() {
        List<PaymentEntity> paymentEntity = paymentService.findAllByBankId(100);
        System.out.println(paymentEntity.toArray());
    }

}

Note: It runs successfully when run with JUnit from @Test annotation.

Thanks, Ahmet

AhmetRufai avatar Feb 04 '21 14:02 AhmetRufai

Have you tried using the instructions at https://mesutyakut.medium.com/acceptance-test-with-gauge-and-spring-boot-f675655d8e ?

zabil avatar Feb 05 '21 07:02 zabil

Yes, I have reviewed this article and the related project. Similarly, when I want to add it to my own project, many exceptions occur in the initialize part and it stays stuck. Spring cannot initialize. Also, there is no DB process in this project. A different project in terms of structure. Some of the exceptions that occur are;

java.lang.UnsupportedOperationException: Reflective setAccessible(true) disabled
	at io.grpc.netty.shaded.io.netty.util.internal.ReflectionUtil.trySetAccessible(ReflectionUtil.java:31)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$4.run(PlatformDependent0.java:233)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:227)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:289)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:92)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<init>(AsciiString.java:223)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<init>(AsciiString.java:210)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.cached(AsciiString.java:1401)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<clinit>(AsciiString.java:48)
	at io.grpc.netty.shaded.io.grpc.netty.Utils.<clinit>(Utils.java:72)
	at io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder.<clinit>(NettyServerBuilder.java:83)
	at com.thoughtworks.gauge.command.StartCommand.execute(StartCommand.java:48)
	at com.thoughtworks.gauge.GaugeRuntime.main(GaugeRuntime.java:23)
jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable
java.lang.IllegalAccessException: class io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$6 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @2de23121
	at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:385)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:693)
	at java.base/java.lang.reflect.Method.invoke(Method.java:556)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0$6.run(PlatformDependent0.java:347)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:312)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent0.<clinit>(PlatformDependent0.java:338)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.isAndroid(PlatformDependent.java:289)
	at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.<clinit>(PlatformDependent.java:92)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<init>(AsciiString.java:223)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<init>(AsciiString.java:210)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.cached(AsciiString.java:1401)
	at io.grpc.netty.shaded.io.netty.util.AsciiString.<clinit>(AsciiString.java:48)
	at io.grpc.netty.shaded.io.grpc.netty.Utils.<clinit>(Utils.java:72)
	at io.grpc.netty.shaded.io.grpc.netty.NettyServerBuilder.<clinit>(NettyServerBuilder.java:83)
	at com.thoughtworks.gauge.command.StartCommand.execute(StartCommand.java:48)
	at com.thoughtworks.gauge.GaugeRuntime.main(GaugeRuntime.java:23)
java.lang.NullPointerException: Cannot invoke "java.io.File.isDirectory()" because the return value of "org.reflections.vfs.Vfs.getFile(java.net.URL)" is null
	at org.reflections.vfs.Vfs$DefaultUrlTypes$3.matches(Vfs.java:233)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:97)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:90)
	at org.reflections.Reflections.scan(Reflections.java:236)
	at org.reflections.Reflections.scan(Reflections.java:203)
	at org.reflections.Reflections.<init>(Reflections.java:128)
	at com.thoughtworks.gauge.scan.ClasspathScanner.createReflections(ClasspathScanner.java:58)
	at com.thoughtworks.gauge.scan.ClasspathScanner.scan(ClasspathScanner.java:33)
	at com.thoughtworks.gauge.connection.MessageProcessorFactory.lambda$new$0(MessageProcessorFactory.java:70)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)
19:34:49.458 [pool-1-thread-1] WARN org.reflections.Reflections - could not create Dir using commons_vfs2 from url file:/C:/Program%20Files/Java/jdk-15.0.1!/jdk.javadoc. skipping.
java.lang.NoClassDefFoundError: org/apache/commons/vfs2/VFS
	at org.reflections.vfs.Vfs$DefaultUrlTypes$7.matches(Vfs.java:281)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:97)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:90)
	at org.reflections.Reflections.scan(Reflections.java:236)
	at org.reflections.Reflections.scan(Reflections.java:203)
	at org.reflections.Reflections.<init>(Reflections.java:128)
	at com.thoughtworks.gauge.scan.ClasspathScanner.createReflections(ClasspathScanner.java:58)
	at com.thoughtworks.gauge.scan.ClasspathScanner.scan(ClasspathScanner.java:33)
	at com.thoughtworks.gauge.connection.MessageProcessorFactory.lambda$new$0(MessageProcessorFactory.java:70)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at java.base/java.lang.Thread.run(Thread.java:832)

AhmetRufai avatar Feb 06 '21 16:02 AhmetRufai

By the way, Spring ran successfully when I tried it with Cucumber. I did the following to make it work;

  1. Firstly I added the following to the build.gradle file:

implementation 'io.cucumber:cucumber-java:6.9.1' implementation 'io.cucumber:cucumber-spring:6.9.1'

  1. I use IntellijIDEA as the IDE. I added the following two plugins:

Gherkin Cucumber for Java

  1. Then I added a feature file for cucumber in the src/test/resources path. (abc.feature)
Feature: Check to run spring with cucumber

  Scenario: Try to run spring with cucumber
    When Check db with spring
  1. Then I created one class and method for the relevant step under src/test/java/glue. (StepDef.java)

  2. Then I extended the StepDef class from the DbCheck class.

  3. Then I added @CucumberContextConfiguration and @SpringBootTest (classes = Application.class) annotations to the StepDef class.

package glue;

import Application
import io.cucumber.java.en.When;
import io.cucumber.spring.CucumberContextConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import payment.DbCheck;

@CucumberContextConfiguration
@SpringBootTest(classes = Application.class)
public class StepDef extends DbCheck{
    @When("Check db with spring")
    public void checkDb() {
        checkData();
    }
}

  1. I rearranged the DbCheck.java class as follows:
package payment;

import model.PaymentEntity;
import service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Slf4j
public class DbCheck {

    @Autowired
    private PaymentService paymentService;

    public void checkData() {
        List<PaymentEntity> paymentEntity = paymentService.findAllByBankId(100);
        System.out.println(Arrays.toString(paymentEntity.toArray()));
    }

}
  1. When I ran the test from the abc.feature file, it ran successfully.

Is a similar method of use possible with Gauge?

AhmetRufai avatar Feb 07 '21 14:02 AhmetRufai

Hi @AhmetRufai , I'm investigating the same issue now, did you manage to find a way to make it working?

0vid1u avatar Mar 31 '21 08:03 0vid1u

Hi @0vid1u, Unfortunately, we couldn't find a solution as we wanted. We had to continue automation with the Cucumber tool.

AhmetRufai avatar Mar 31 '21 21:03 AhmetRufai

@AhmetRufai @0vid1u - sorry to hear this didn't work. I am not familiar with Spring Boot, and there's a good chance that gauge-java may need some tweaking to get this working.

I can work on this, but I'd need a sample project where I can see this issue.

sriv avatar Apr 05 '21 01:04 sriv

I have Spring Framework working with gauge (1.4.0 / Gauge-java 0.7.15) perfectly with version 5.2.4.RELEASE. however, upgrading to newest version is causing the issue noted here. i will try to investigate further... Hopefully, can get it to work.

alpha1592 avatar Aug 25 '21 17:08 alpha1592

Could you please share working example with older release. We can try to investigate it and interested to make it works. Thanks

bholya avatar Aug 25 '21 20:08 bholya

These errors are usually related to logback with gauge.

I had to exclude all 1.2.* versions and replace with:

xml <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.3.0-alpha5</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.3.0-alpha5</version> </dependency>

jbadeau avatar Oct 29 '21 08:10 jbadeau