Junit5- jupiter all tests suite #BeforeAll #AfterAll not working - spring-boot

The before and after methods not working in JUnitPlatform.
The code is below.
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.runner.RunWith;
#RunWith(JUnitPlatform.class)
#SelectClasses({
MyControllerTest.class
})
public class AdminAppTest {
#BeforeAll
public static void setUp() {
System.out.println("setting up");
}
#AfterAll
public static void tearDown() {
System.out.println("tearing down");
}
}
I just want to running before and after methods.
Thank you

Just came across this after running into the same problem, #AfterAll and also #AfterEach annotated methods weren't called. In my case the problem was that an incorrect import for JUnit4 sneaked into my test class, I was importing org.junit.Test instead of org.junit.jupiter.api.Test. Once I fixed this my annotated methods were happily called again.

I may cite the JUnit 5 migration tipps:
#Before and #After no longer exist; use #BeforeEach and #AfterEach instead.
#BeforeClass and #AfterClass no longer exist; use #BeforeAll and #AfterAll instead.
But these annotations should be used in your test class. The methods in your suite class will not be invoked this way. And you should be aware of the fact that suites and JUnit 5 are still work in progress (see Issue 744).

You may want to check that org.junit.jupiter:junit-jupiter-engine is in your classpath.
However, recent versions of build tools (Maven with surefire plugin, Gradle, Eclipse, IntelliJ, etc.) support junit-platform. Therefore you do not need to use JUnit4 with a backward-compatible runner.
Usually you can be in the following cases:
creating new project, in which case you can start directly using only JUnit-Jupiter (and without having JUnit4 in your classpath)
migrating a project from JUnit4 to JUnit5. Here you will want to have two engines: JUnit-Vintage, which covers retrocompatibility for existing tests using the JUnit4 API, and JUnit-Jupiter who offers more flexibility, including the composition of extensions (having Spring, Mockito and parameterized tests features at the same time for example)
Using a JUnit4 runner to run JUnit-Jupiter tests is really a corner case, when you are constrained by an environment (build tool and/or IDE) that you cannot change.
For more details, sample projects are made available by the JUnit team:
Gradle project with JUnit-Jupiter
Maven project with JUnit-Jupiter
Maven project migrating from JUnit4 to JUnit5
Hope this helps !

Related

Test OSGi project with JUnit4

I have a maven project. I created a JUnit4 test class for one of my classes using the Idea wizard.
package com.mst.ica.dao.support;
import junit.framework.TestCase;
import static org.junit.Assert.*;
public class DbNamingStandardTest extends TestCase {
}
When I tried to run my test, I got the following error in my output and nothing more.
OSGi in module 'com.mst.ica.integration.api': java.lang.NoClassDefFoundError: aQute/bnd/osgi/Builder
Does anybody know what it means and how to run my test?
You seem to be mixing JUnit 3 (TestCase) and JUnit 4 (org.junit.*).
See the osgi-test project (https://github.com/osgi/osgi-test/) which provides support libraries for testing in OSGi as well as some examples. In particular, the org.osgi.test.junit4 has a test case which runs in OSGi using JUnit 4 (either plain JUnit4 or using the vintage engine with JUnit 5).

Cucumber does not work with #EnableIf annotation

I want to enable cucumber tests with #EnableIf annotation, but it is not working even if i add #EnabledIf("false")
here is the code that i use :
#EnabledIf("false")
#SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
#CucumberContextConfiguration
public class CucumberRoot {
private int port = 8080;
protected String DEFAULT_URL = "http://localhost:" + port + "/";
#Autowired
protected TestRestTemplate template;
}
for other integration tests beside cucumber i am able to use #EnableIf annotation.
Is there any way to achieve that ?
No.
https://junit.org/junit5/docs/current/user-guide/
1.1. What is JUnit 5?
Unlike previous versions of JUnit, JUnit 5 is composed of several different modules from three different sub-projects.
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the TestEngine API for developing a testing framework that runs on the platform. Furthermore, the platform provides a Console Launcher to launch the platform from the command line and a JUnit 4 based Runner for running any TestEngine on the platform in a JUnit 4 based environment. First-class support for the JUnit Platform also exists in popular IDEs (see IntelliJ IDEA, Eclipse, NetBeans, and Visual Studio Code) and build tools (see Gradle, Maven, and Ant).
JUnit Jupiter is the combination of the new programming model and extension model for writing tests and extensions in JUnit 5. The Jupiter sub-project provides a TestEngine for running Jupiter based tests on the platform.
JUnit Vintage provides a TestEngine for running JUnit 3 and JUnit 4 based tests on the platform.
And like JUnit Jupiter and JUnit Vintage, Cucumber is a test engine on the JUnit Platform. The annotation you are using is JUnit Jupiter annotation and can only be understood by JUnit Jupiter. Neither JUnit Vintage nor Cucumber can understand it.
However Cucumber does support OpenTest4Js TestAbortedException. So you can use a before hook to stop a scenario before any step are executed. Either by throwing the exception directly or using Assumptions from JUnit Jupiter.
#Before
public void before() {
boolean condition = // decide if tests should abort
if (condition)
throw new TestAbortedException()
}
#Before
public void before() {
boolean condition = // decide if tests should abort
Assumptions.assumeTrue(condition, "Condition not met");
}

Unit testing Spring Boot application Service layer

I'm a bit confused about the test capabilities and utilities provided by Spring Boot.
I'm using spring-boot-starter-test in my project and I'd like to unit test my services without the database connection
At the moment I'm using #WebMvcTest for contoller test suites and #SpringBootTest for all the other test classes.
But I read somewhere that #SpringBootTest is meant to be used only in integration tests...
Reading documentation I didn't understood what's the suggested approach for services. Should I only test them in integration with repos?
UPDATE
That's an excerpt of a test class for one of my services:
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#SpringBootTest
internal class SignupServiceTest(
#Autowired val signupService: SignupService
) {
#MockkBean
lateinit var userRepository: UserRepository
#Test
fun `should return exception if username already used`() {
every { userRepository.findByUsername("registered-user") } returns fakeUser(username = "registered-user")
assertThatThrownBy {
signupService.createNewAccount(fakeSignupForm(username = "registered-user"))
}.isExactlyInstanceOf(UsernameNotAvailableException::class.java)
}
// ... other tests
}
Using #SpringBootTest for unit tests is a bit of a overkill. Because this would boot up the whole application context.
To test individual (service) classes I would go with #RunWith(MockitoJUnitRunner.class) and instead of #Autowired and #MockBean use #Mock and #InjectMocks(If you use constructor injection, you wouldn't have to use this. which would be the better option)
You could still use #Autowired with #ContextConfiguration and load specific classes(if there are not too many transitive dependencies)
If you do not want to use mocks, then you can use embedded databases and use #DataMongoTest or #DataJpaTest and use Springboot testing capabilities.
Keep it simple....
You should favor implementing unit tests to test your business logic (tests running without Spring, plain JUnit tests) over integration tests (tests starting a Spring container, #SpringBootTest) as they are more lightweight and give you feedback a lot faster.
Quote from Spring Boot doc
One of the major advantages of dependency injection is that it should make your code easier to unit test. You can instantiate objects by using the new operator without even involving Spring. You can also use mock objects instead of real dependencies.
Often, you need to move beyond unit testing and start integration testing (with a Spring ApplicationContext). It is useful to be able to perform integration testing without requiring deployment of your application or needing to connect to other infrastructure.
try to mock the calls to database using mockito, or use h2 database for the tests
I was previously using #SpringBootTest as well then realized it was also trying to connect to my database, which should not be needed since it's a simple service test and all dependencies are mocked. After a bit of research I found this solution works quite well. Also note now my spring properties were not being injected so I used #Spy to create a pojo property object with some test values.
#ExtendWith(MockitoExtension.class)
public class MyServiceTest {
/**
* This is the bean under test as it is not a mock
*/
#InjectMocks
private MyService myService;
#Mock
private OtherService otherService;
#Spy
private MyServiceProperties properties = mockProperties();
#BeforeEach
public void configureMocks() {
given(this.otherService.getData(any())).willReturn(mockDataResponse());
}
#Test
void testMyServiceReport_Success() {
myService.runReport();
//assert response as needed
verify(otherService, times(1)).getData(any());
}
Also here is some help with the imports which can sometimes be confusing:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.times;
import static org.mockito.BDDMockito.verify;

Using aspectj in Hibernate entity

I have entity class like this:
package tr.com.example.model.porting
...//omitting imports
#Configurable
#Data
#Entity
public class PortOut{
public void handleRequest(Long portingId) {
processRequest(portingId);
...
}
}
And here is my aspect code in different class annotated with #Aspect and #Component:
#Around("execution(* tr.com.example..PortOut.handleRequest(..))")
public void handlePortingProcessAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
joinPoint.proceed();
log.debug(log.debug("[POM]:{} is executed with parameters:{}", joinPoint.toShortString(), joinPoint.getArgs()))
}
Normally, my aspect code works fine for other Spring managed classes such as using #Service, #Component annotation. I am using https://github.com/subes/invesdwin-instrument as a weaving agent and also using Lombok.
I tried this link(along with other so posts). But since I am using Lombok, I cannot directy compile with aspectj compiler for weaving #Configurable classes, it doesn't work with Lombok as I found out.
https://groups.google.com/forum/#!topic/project-lombok/ZkLsTZVSgD4
Shortly, what I want is using aspectj for logging some methods's arguments, but I can't use it in any Hibernate entity class, other than that it works fine. How to get it working in entity classes?
Here you find the explanation why Lombok and AspectJ do not like each other.
What is said to work though, is to delombok the Lombok-annotated source code and then normally compile the generated source code with the AspectJ compiler (e.g. via AspectJ Maven plugin, which is what I use all the time in Maven projects). Assuming you do use Maven, also the delombok step can be done with Lombok Maven plugin. If you assign the right phases to the respective plugins, it should be possible to fully automate the build process.
Disclaimer: I have never used Lombok in my whole life, but know a thing or two about AspectJ and Maven.

Unable to run spring-boot-test

I am new to Spring-boot.
We are trying to practice spring-boot-test by adding the following Java class in this Spring guide for testing purpose.
However, it turns out that we are not able to trigger this Java class. In other words, there is no any test result showing up in the our eclipse console.
Could someone suggest us where we do wrong?
Thanks!
GreetingControllerTest.java
package hello;
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class GreetingControllerTest {
private RestTemplate restTemplate = new RestTemplate();
#Test
public void testGreeting() {
System.out.println("Where is my TEST?????!!!!!!");
String url = "http://localhost:8080/greeting";
assertNotNull(restTemplate.getForObject(url, Greeting.class));
}
}
The Spring Framework does not run (trigger) tests. Rather, a testing framework like JUnit or TestNG runs tests.
Your code appears to be fine. So, assuming that the example you supplied compiles (i.e., has the correct package imports) and assuming that the #Test annotation you have declared is #org.junit.Test, then you simply need to run the test as a JUnit test.
Your IDE (e.g., Eclipse, IntelliJ, NetBeans) and build framework (e.g., Maven, Ant, Gradle) should provide support for running JUnit tests.
Regards,
Sam

Resources