Running multiple tests using RestAssured serially - spring-boot

I have a Spring Boot application which is capable of running Integration tests using Rest Assured.
There is a single test class which has multiple test cases. I wish to run the test cases serially as given in the class.
public class ItemControllerTest{
#Before
public void setUp(){
...
}
#Test
public void test1(){
...
}
#Test
public void test2(){
...
}
}
When I run integration test,it seems test2 is getting executed before test1.
But I want them to run in the order they are written

I am not familiar with spring-boot, but if you are using Junit to run your tests, then you can run them serially by adding the following annotation above your class:
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ItemControllerTest{
// tests will run in order here
}

Related

Launch application before tests on condition

I have rest-assured tests marked with #SpringBootTest (which allows to start application before executing tests). But I have two use cases:
Run tests locally (current setup is ok for that).
Run same tests on already running host (not ok, as application is started before executing tests).
Is there any way to sometimes ignore #SpringBootTest or somehow turn off application initialization?
Adding minimal example:
#RunWith(SpringRunner.class)
//In case service.host provided: no need to run application
#SpringBootTest
public class RestTest {
#Value("service.host")
private String host;
#Before
public void setUp() {
if (StringUtils.isNotEmpty(host)) {
RestAssured.baseURI = host;
}
}
#Test
public void test() {
RestAssured.get("/test").then().assertThat().statusCode(HttpStatus.OK.value());
}
}

tun unit tests in parallel and other test sequentially in the same run spring boot kotlin

i am having an issue to understand how can i run all the unit tests in my boot spring application(kotlin) in parallel while the springBootTests and the dataJpaTests will run one after the other(becouse they are failing due to shared context where running in parallel),
my application structure is separated to different models and each model have it's unit,springBootTests and dataJpaTets, like this:
-module 1:
unit test 1
unit test 2
data jpa test 1
data jpa test 2
spring boot test1
-module 2:
unit test 1
unit test 2
unit test 3
data jpa test 1
spring boot test1
i used the following properties from https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution:
junit.jupiter.execution.parallel.enabled = true
junit.jupiter.execution.parallel.mode.default = concurrent //tests in each class run in parallel
junit.jupiter.execution.parallel.mode.classes.default = concurrent //classes run in parallel
but it is not helping becouse there is no way to exclude the springBoot and dataJpa tests from the parallization.
also,i tried to put the #Execution(SAME_THREAD) on all the dataJpa and springBoot test but still
the classes itself runed in parallel and test was colliding
*i use --test *test commend to run all the tests together
Spring uses Junit
By default, JUnit Jupiter tests are run sequentially in a single thread.
Running tests in parallel — for example, to speed up execution — is available as an experimental feature since version 5.3
Source: https://junit.org/junit5/docs/current/user-guide/#writing-tests-parallel-execution
Using pure Junit
#Execution(ExecutionMode.CONCURRENT)
class MyTest {
#Test
void test1() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Test1 " + Thread.currentThread().getName());
}
#Test
void test2() throws InterruptedException {
Thread.sleep(1000);
System.out.println("Test 2! " + Thread.currentThread().getName());
}
}
source:
https://stackoverflow.com/a/55244698/3957754
https://www.swtestacademy.com/junit5-parallel-test-execution/
Using spring + maven + junit
<build>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<parallel>methods</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
</configuration>
</plugin>
</build>
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = Spring5JUnit4ConcurrentTest.SimpleConfiguration.class)
public class Spring5JUnit4ConcurrentTest implements ApplicationContextAware, InitializingBean {
#Configuration
public static class SimpleConfiguration {}
private ApplicationContext applicationContext;
private boolean beanInitialized = false;
#Override
public void afterPropertiesSet() throws Exception {
this.beanInitialized = true;
}
#Override
public void setApplicationContext(
final ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
#Test
void test1A() {
System.out.println(Thread.currentThread().getName()+" => test1A");
}
#Test
void test1B() {
System.out.println(Thread.currentThread().getName()+" => test1B");
}
#Test
void testC() {
System.out.println(Thread.currentThread().getName()+" => test1C");
}
}
Sources:
https://www.baeldung.com/spring-5-concurrent-tests
https://javabydeveloper.com/junit-5-parallel-tests-execution-and-resourcelock-examples/
Running junit tests in parallel in a Maven build?
Running junit testcases in parallel using maven
Simple tests are "almost parallel"
According to this and my tests, simple junit tests are executed almost parallel
public class Hello1Test {
#Test
public void myTest() throws Exception {
System.out.println(new Date());
assertTrue(true);
}
}
mvn test
NOTE: If you add some Thread related in the test, they are executed sequentially
#Test
public void myTest() throws Exception {
System.out.println(new Date());
Thread.sleep(2000);
assertTrue(true);
}
Exclude some tests
According to this you could use -Dtest to pick or exclude specific tests
mvn test -q
run all tests
mvn test -q -Dtest='Hello1*'
run only test with name Hello1*
mvn test -q -Dtest='!Hello1*, !Hello2*'
run all tests except Hello1* and Hello2*
Tips
Use the shell, it never lies
According to your ide (eclipse or intellij), you should be able to configure jvm args like : mvn test -q -Dtest
Add date and test name to the log to verify if they are parallel or sequential
Create a minimal reproducible project to help you. Example: https://github.com/jrichardsz/spring-boot-templates/tree/master/011-filter-tests

JUnit 5 test suite choose test methods

Having some test classes with Junit 5 and Spring Boot REST controller testing.
#SpringBootTest
#AutoConfigureMockMvc
public class TestClassA {
#Autowired
private MockMvc mockMvc;
#Test
#WithMockUser
public void testMethod1() {
...
}
#Test
#WithMockUser
public void testMethod2() {
...
}
// more test methods
}
#SpringBootTest
#AutoConfigureMockMvc
public class TestClassB {
#Autowired
private MockMvc mockMvc;
#Test
#WithMockUser
public void testMethod1() {
...
}
// more test methods
#Test
#WithMockUser
public void testMethodX() {
// requires that TestClassA.testMethod2()
// must be run first
}
}
The test classes run, each testing a specific REST controller, but how to achieve a new test method TestClassB.testMethodX()?
I thought to create a test suite in JUnit 5 and specify which test methods to run, also in order:
1. run TestClassA.testMethod2()
2. run TestClassB.testMethodX()
I know about two annotations:
- #SelectPackages
- #SelectClasses
But selecting specific test methods not possible?
Is this achievable with JUnit 5?
I cannot answer both of your questions, but at least I can give you a hint on how to choose a set of test methods which should be run.
For my understanding unit/integration tests should not rely on a specific order to pass successfully. Is it really necessary, or can you realize important requirements for tasks using things like #Before annotations?
In my setup, I run Spring Boot with Gradle.
JUnit Tags & Filtering
JUnit 5 allows to add tag(s) to your test methods, using the #Tag annotation. With this feature it is possible to filter your test methods on test execution. Have a look at baeldung.com for a short tutorial.
Tag your test methods
Mark your test methods with a tag fitting to your purpose, like this.
#Test
#Tag("IntegrationTest")
public void testMethod1() {
...
}
// more test methods
#Test
#Tag("UnitTest")
public void testMethodX() {
...
}
Run tagged methods
Run tagged methods using IntelliJ
If you use the IntelliJ IDE, it is rather simple to run test methods with specific tags. See jetbrains.com docs or stackoverflow.
Run -> Edit Configurations... -> + (Add new configuration) -> JUnit
As Test kinds choose Tags
Insert your desired tag at Tag expression
Run tagged methods using Gradle
In case you want to run your test methods for instance in a continuous integration pipeline you probably run the tests using Gradle or Maven. For Gradle I can also show you a possibility to run methods with specific tags.
Open build.gradle
For dependencies you probably already have integrated the JUnit 5 framework, similar to this:
dependencies {
// [...]
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
// [...]
}
You also should have a test task.
test {
useJUnitPlatform()
}
The command $ gradlew test would now run all defined test methods. So, to run just a specific set of methods, I suggest to create custom tasks, like this.
test {
useJUnitPlatform()
}
task unitTests(type: Test) {
useJUnitPlatform {
includeTags 'UnitTest'
}
}
task integrationTests(type: Test) {
useJUnitPlatform {
includeTags 'IntegrationTest'
}
}
After that, you are able run the tasks on the command line interface, e.g.: $ gradlew unitTests and it would just run the tasks you defined in your custom task.

How to order Tests while building Spring Boot application

I am building spring boot application with unit testing. I have entities those are dependent on each other, Eg: I have User and Roles. To create User i should need Roles. I am testing roles and user object resources with MockMvc. I created Test class for Each Entity. When i run test UserTest class is executing Before Role Test class. So, all my tests are failing. I need help to run Test classes in an order.
As I mentioned in the comments, the best solution to such a problem is to avoid dependencies between test classes.
This can be achieved via proper test fixture setup and tear down (e.g., #Before and #After methods in JUnit 4).
Having said that, however, it is possible to order test classes in JUnit 4 if you execute them via a suite as in the following example.
#RunWith(Suite.class)
#SuiteClasses({RoleTests.class, UserTests.class})
public class MyTestSuite {
public static class RoleTests {
#Test
public void roleTest() {
System.err.println("roleTest");
}
}
public static class UserTests {
#Test
public void userTest() {
System.err.println("userTest");
}
}
}
That always prints:
roleTest
userTest

How do I get JMeter Junit Request Sampler to run #BeforeClass?

I have the following Test class...
#RunWith(JUnit4.class)
public class AdminSpecTest extends BaseTest{
#BeforeClass
public static void getLogin(){
System.out.println("getLogin");
...
}
#Test
public void testAdminPage(){
System.out.println("testAdmin");
...
}
}
When I try to create a JUnit sampler in JMeter I run the test and it fails. In the terminal window I see...
testAdmin
but there is no getLogin. Why isn't BeforeClass getting called? Can I get this to happen?
Accoding to JMeter's JUnit you can use #Before instead for setup before test executes.
The following JUnit4 annotations are recognised:
#Before
treated the same as setUp() in JUnit3
#BeforeClass, #AfterClass
treated as test methods so they can be run independently as required
Yes you should be able to do this, but this solution involves adding another class at least temporarily while you are performance testing with JMeter. You then use this class to call the other test class (AdminSpecTest). Make sure you select this new class and method in JMeter's Junit Sampler dropdowns.
package test;
import org.junit.Test;
import org.junit.runner.JUnitCore;
public class TestRunner
{
public TestRunner()
{
}
#Test
public void runTests()
{
JUnitCore junit = new JUnitCore();
junit.run(AdminSpecTest.class);
}
}

Resources