Test class in spring dosn't work properly - java

I would like to test my controller class. But I couldn't manage to run springBootTest class. My project written in spring boot. We are writing REST API using spring boot.
When I try to excute following test class. I still get following line from terminal.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import static org.assertj.core.api.Assertions.assertThat;
/*
*
* #A Sabirov Jakhongir
*
*/
#SpringBootTest
#WebMvcTest
public class PrivilegesControllerTest {
#Autowired
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
I put here all needed dependency for testing from my project.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-launcher -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.3.2</version>
<scope>test</scope>
</dependency>
What might be cause of not working of test Class.

With Junit5 and #SpringBootTest will load the full application, I had faced the same issue before, you can find details about the question here and answer here.
The solution for this is to use your test without #SpringBootTest.
The solution to your test class is as below.
#ExtendWith(MockitoExtension.class)
public class PrivilegesControllerTest {
#InjectMocks
private PrivilegesController privilegesController;
#Test
public void add() {
assertThat(privilegesController).isNotNull();
}
}
You can also use #ExtendWith(SpringExtension.class) instead of #ExtendWith(MockitoExtension.class)

To test spring boot application is creating your controller, use #SpringBootTest annotation, and to test the behavior or responsibility of the controller is better to use #WebMvcTest. No need to annotate both the annotation to one class.
There are two cases to test the controller's responsibility.
With running Server
Without Server
For 1st Case, you can use #SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) to start a server with a random port.
For 2nd Case, use #WebMvcTest for testing the web layer.
All the test cases are written with the following signature:
#Test
public void test_Name() throws Exception {
//your test definition
}
You can also read the Official Documentation of Spring Boot https://spring.io/guides/gs/testing-web/

Related

TestNG #BeforeMethod onlyForGroups option removed

I was looking for some way to have some #beforeMethod logic executing only for a group of java unit tests (using TestNG ).
I found on TestNG documentation:
onlyForGroups: Only for #BeforeMethod and #AfterMethod. If specified,
then this setup/teardown method will only be invoked if the
corresponding test method belongs to one of the listed groups.
Which seems to be what I'm looking for.
But when I try to use it, it's not implemented in #BeforeMethod and #AfterMethod annotations. I couldn't find find any information on the web about it missing.
Maven dependency :
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.2</version>
<scope>test</scope>
</dependency>
Thanks for the help
Upgrade you version, as you see in Changes, it was added after 6.14.3 version
Fixed: GITHUB-549 and GITHUB-780: Introduce onlyForGroups attribute for #BeforeMethod and #AfterMethod (Sergei Tachenov)
Notice the version of TestNG used in the dependency.
<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.4.0</version>
<scope>test</scope>
</dependency>
</dependencies>
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class TestNgBeforeMethodAnnotation {
#BeforeMethod(onlyForGroups = {"Group1"}, groups = {"Group1"})
public void setupForGroup1()
{
System.out.println("Before Method for Group 1 called");
}
#Test(groups = {"Group1"})
public void testCaseInGroup1()
{
System.out.println("testCaseInGroup1");
}
}

spring-webmvc/hibernate-validator not invalidating bad data during test

I'm reading Spring In Action, and I'm working through the example spittr web application for spring-mvc. The book discusses using javax.annotation.constraints to describe valid data, e.g.
import javax.validation.constraints.*;
public class Spitter {
#NotNull
#Size(min=5, max=16)
private String username;
//...
}
Then, it says, you can apply validation to a method using the #Valid decorator for arguments, e.g.
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
#Controller
#RequestMapping({"/spitter"})
public class SpitterController {
#RequestMapping(value="/register", method=POST)
public String processRegistration(#Valid Spitter spitter, Errors errors) {
if (errors.hasErrors()) {
return "registerForm";
}
return "redirect:/spitter/" + spitter.getUsername();
}
//...
}
To check my understanding of the material, I tried writing some tests to see the method react to invalid data:
import org.junit.Test;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultBuilders.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
public class SpitterControllerTest {
#Test
public void shouldNotProcessEmptyRegistration() throws Exception {
standaloneSetup(new SpitterController())
.build()
.perform(post("/spitter/register"))
.andExpect(view().name("registerForm"));
}
#Test
public void shouldNotProcessInvalidRegistration() throws Exception {
standaloneSetup(new SpitterController())
.build()
.perform(post("/spitter/register").param("username", "x"))
.andExpect(view().name("registerForm"));
}
//...
}
And I was surprised when the tests failed
shouldNotProcessEmptyRegistration(spittr.web.SpitterControllerTest) Time elapsed: 0.013 sec <<< FAILURE!
java.lang.AssertionError: View name expected:<registerForm> but was:<redirect:/spitter/null>
shouldNotProcessInvalidRegistration(spittr.web.SpitterControllerTest) Time elapsed: 0.013 sec <<< FAILURE!
java.lang.AssertionError: View name expected:<registerForm> but was:<redirect:/spitter/x>
I don't know what I'm doing wrong. I know what happens at test time has a good deal to do with what's on the classpath:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.13.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.0.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
I think it's likely that I'm missing some dependency the book didn't bother to mention, but at this point I'm not really sure what I'm doing wrong.
Most of what I've been able to find by googling discusses spring-boot, which I'm trying to put off for now; I'd like to understand spring first before I start trying to understand what spring-boot brings to the table (but Spring Boot In Action is next on my reading list).
What do I need to do to fix my code so that the controller successfully detects the invalid data when testing?
Seems like in your code your are requiring the username of a spitter to not be null, however that does not mean that the entire object cant be null. In your current setup the request body is optional. You could try:
public String processRegistration(#RequestBody #Valid Spitter spitter, Errors errors)
By default #RequestBody makes the body required.

resilience4j-spring-boot-2 annotations (#Retry, #CircuitBreaker...) are completely ignored

I spent a whole day trying to find why this does not work so I think it might be useful if I share the question and the answer.
The Resilience4j library provides an elegant annotation-based solution from Spring Boot 2. All you need to do is just annotate a method (or a class) with one of the provided annotations, such as #CircuitBreaker, #Retry, #RateLimiter, #Bulkhead, #Thread and the appropriate resilience pattern is automagically added.
I added the expected dependency to the Maven pom.xml:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>${resilience4j.version}</version>
</dependency>
Now the compiler is happy, so I can add the annotations:
...
import org.springframework.stereotype.Service;
import io.github.resilience4j.retry.annotation.Retry;
...
#Service
public class MyService {
...
#Retry(name = "get-response")
public MyResponse getResponse(MyRequest request) {
...
}
}
The program compiles, runs, however the annotations are completely ignored.
According to the resilience4j-spring-boot2 documentation:
The module expects that spring-boot-starter-actuator and spring-boot-starter-aop are already provided at runtime.
So the whole trick is to add also the missing dependencies to the Maven pom.xml:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Unable to run unit test cases

I am writing test cases for my project using Junit5, when I run a test cases all the test cases passes, but some of them gives me below error in console
WARNING: TestEngine with ID 'junit-jupiter' failed to execute tests
java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.getFailedComparison(JUnit5TestListener.java:133)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.notifyIfNotSuccessful(JUnit5TestListener.java:89)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestListener.executionFinished(JUnit5TestListener.java:71)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry$CompositeTestExecutionListener.lambda$executionFinished$3(TestExecutionListenerRegistry.java:77)
at java.util.ArrayList.forEach(Unknown Source)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry.notifyTestExecutionListeners(TestExecutionListenerRegistry.java:51)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry.access$100(TestExecutionListenerRegistry.java:27)
at org.junit.platform.launcher.core.TestExecutionListenerRegistry$CompositeTestExecutionListener.executionFinished(TestExecutionListenerRegistry.java:77)
at org.junit.platform.launcher.core.ExecutionListenerAdapter.executionFinished(ExecutionListenerAdapter.java:56)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.reportCompletion(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)
for e.g.
Mockito.verify(exportFile, Mockito.times(1)).exportCsvFile(Mockito.anyList(), Mockito.anyString());
Mockito.verify(exportFile, Mockito.times(2)).exportCsvFile(Mockito.anyList(), Mockito.anyString());
Mockito.verify(exportFile, Mockito.times(3)).exportCsvFile(Mockito.anyList(), Mockito.anyString();
Every time test case passes, but for second and third case I am seeing java.lang.NoClassDefFoundError: junit/framework/ComparisonFailure
Below is how my pom looks like:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- exclude junit 4 -->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- junit 5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
Below is how my test class looks like (provided necessary part of the class).
public class AccountServiceTest {
AccountService AccountService;
#Mock
ExportFile exportFile;
#BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
accountService = new AccountService(exportFile);
}
#Test
public void testFileExport() {
accountService.process(partner.getName());
Mockito.verify(exportFile).exportCsvFile(Mockito.anyList(), Mockito.anyString());
}
}
If you can upgrade your spring-boot-starter-test to at least 2.2.0.RELEASE it will bring you JUnit 5 (the exclusion is also not necessary if you want run JUnit4 and JUnit5 tests at the same time). Using only spring boot starter dependencies is a good way to handle incompatible version issue between dependencies as spring boot manages that for you.
If you want run a test with JUnit5 and Mockito, your class should look like this (the object you want to test is annotated with #InjectMocks and it's dependency you want mock with #Mock and the class test with #ExtendWith(MockitoExtension.class)) :
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
public class AccountServiceTest {
#Mock
ExportFile exportFile;
#InjectMocks
AccountService accountService;
#Test
public void testFileExport() {
accountService.process("");
Mockito.verify(exportFile).exportCsvFile(Mockito.anyList(), Mockito.anyString());
}
}

Spock spring module results in NoSuchMethodError when running the test

I am using the following spock dependency
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.0-groovy-2.4</version>
<scope>test</scope>
</dependency>
I wrote this test
class JsonIncludeResolverTest extends Specification {
JsonIncludeResolver uut;
def "test"(){
expect:
true
}
}
the test succeeds
Now I want to use Spring to inject JsonIncludeResolverwithin the specification.
JsonIncludeResolver is annotated with #Component and is injected successfully when running the application. Both tests and component are placed in the same maven module.
I read about spring-spock here: How to inject spring beans into spock test
Therefore I added this dependency version
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
after adding this dependency running the s
Exception in thread "main" java.lang.NoSuchMethodError: org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive(Ljava/lang/Class;Ljava/lang/Class;)Z
at org.spockframework.spring.SpringExtension.isSpringSpec(SpringExtension.java:83)
at org.spockframework.spring.SpringExtension.visitSpec(SpringExtension.java:59)
at org.spockframework.runtime.ExtensionRunner.runGlobalExtensions(ExtensionRunner.java:46)
at org.spockframework.runtime.ExtensionRunner.run(ExtensionRunner.java:40)
at org.spockframework.runtime.Sputnik.runExtensionsIfNecessary(Sputnik.java:88)
at org.spockframework.runtime.Sputnik.getDescription(Sputnik.java:55)
at com.intellij.junit4.JUnit4IdeaTestRunner.getDescription(JUnit4IdeaTestRunner.java:78)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:50)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
I then tried to use the proper annotations
#ContextConfiguration
class JsonIncludeResolverTest extends Specification {
#Autowired
JsonIncludeResolver uut;
def "test"(){
expect:
uut != null
}
}
Still the result is the above exception.
The groovy test is under /src/test/groovy which is a working as you could see in the first successful run of the test.
Try upgrading Spock to 1.1 as follows:
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
org.spockframework.util.ReflectionUtil.isAnnotationPresentRecursive() has been introduced since version 1.1 by this commit.

Categories