JUnit exluding base class from tests in Spring context - java

All my unit tests have the same header with Spring annotations:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:spring/spring-master.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
#Transactional()
I moved them to base class and all my tests now extend it:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:spring/spring-master.xml"})
#TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = false)
#Transactional()
public class DomainObjectBaseTest {
...
public class SomeTest extends DomainObjectBaseTest {
Now when I'm running all tests I'm getting for the DomainObjectBaseTest:
java.lang.Exception: No runnable methods
My question is how can I avoid it? I can remove #RunWith, but in this case, I'll have to apply the annotation to all other tests. Too many extra code,don't like it.
Probably, as an alternative, I can somehow in Spring group annotations, name it, and refere to the group from my tests, please tell me if it is possible. In this case I'll remove base class at all.
And probably there is a way to tell that this class should not be tested. I'm using JUnit4.

Make your base class abstract. The problem is that I believe it is not abstract, so test runner tries to run it and fails for this (IMHO stupid) reason. But it ignores abstract classes.

Related

How to ignore a quarkus test

I am testing my Quarkus application, and I would like to ignore some of my tests.
The test class is annotated with #io.quarkus.test.junit.QuarkusTest, and each method with #org.junit.jupiter.api.Test
I'm trying to use the #org.junit.Ignore annotation, but it's not working, the ignored tests are executed anyway.
This is the code:
#QuarkusTest
#TestHTTPEndpoint(MyResource::class)
class MyResourceTest {
#Test
#Ignore
fun `to be ignored`() {
assertTrue(false)
}
}
Does anyone know how can I achieve this?
You can use #Disabled annotation
You can also conditionally run tests with assumptions.

How to use MongoRepository in test?

I want to use a MongoRepository in a #DataMongoTest. I can't add it in #ContextConfiguration since it's an interface.
I ended up doing the following:
#DataMongoTest
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {MyService.class})
#EnableMongoRepositories("com.exmaple.path.to.mongorepos")
which works, but I don't like the fact that I need to set this String value of the base package. Interestingly, #EnableMongoRepositories alone doesn't work.
Is there another method to instantiate a MongoRepository in a unit test?
try replacing:
#ContextConfiguration(classes = {MyService.class})
#EnableMongoRepositories("com.exmaple.path.to.mongorepos")
to:
#Import({MyService.class})

How to make a common #Testcontainer for multiple Jupiter tests?

I have an abstract controller test class and its inheritor with units, but I want to separate tests into different classes according to the controller method they are testing. Every time I create the second test-class and put a test in it I get the following error:
Failed to validate connection org.postgresql.jdbc.PgConnection#28806954 (This connection has been closed.). Possibly consider using a shorter maxLifetime value.
I have the following base class:
#SpringBootTest
#AutoConfigureMockMvc
#Testcontainers
public abstract class ControllerAbstractTest {
#Container
private final static PostgreSQLContainer postgreSQLContainer;
static {
postgreSQLContainer = new PostgreSQLContainer<>("postgres:13")
.withDatabaseName("my-test-db")
.withUsername("a")
.withPassword("a");
postgreSQLContainer.start();
System.setProperty("spring.datasource.url", postgreSQLContainer.getJdbcUrl());
System.setProperty("spring.datasource.password", postgreSQLContainer.getPassword());
System.setProperty("spring.datasource.username", postgreSQLContainer.getUsername());
}
// other methods
Tests work just fine in a single inheritor class.
I am using org.testcontainers:junit-jupiter:1.16.2, same version for postgresql and spring boot 2.5.6. #Test annotation is from org.junit.jupiter.api.Test
I have tried adding #Testcontainers to inheritors and removing it from the base test class, but it did not help.
I prefer to start a container in a separate configuration so the test classes are not required to extend a specific abstract class.
/**
* Starts a database server in a local Docker container.
*/
#TestConfiguration
public class TestDatabaseConfiguration {
private static final PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer<>("postgres:13")
.withDatabaseName("my-test-db")
.withUsername("username")
.withPassword("password");
static {
postgreSQLContainer.start();
System.setProperty("spring.datasource.url", postgreSQLContainer.getJdbcUrl());
System.setProperty("spring.datasource.password", postgreSQLContainer.getPassword());
System.setProperty("spring.datasource.username", postgreSQLContainer.getUsername());
}
}
Test classes that want to connect to the single shared database server are annotated with:
#Import(TestDatabaseConfiguration.class)

Does order of annotations matter in SB application?

It seems to me that having annotations in different order breaks my build.
Does annotations order matter?
Answers from above say, in general, annotations order should not matter. In my case it is breaking.
This is module commons
#ConditionalOnProperty(value = "calculatorEnabled", havingValue = "true")
#Component
class Calculator {
// some logic
}
#ConditionalOnBean(Calculator.class)
#Service
class CalculationService {
private final Calculator calculator;
#Autowired
public CalculationService(final Calculator calculator) {
this.calculator = calculator;
}
// some logic
}
#RequestMapping(value = "/calculations", produces = MediaType.APPLICATION_JSON_VALUE)
#ConditionalOnBean(CalculationService.class)
#RestController
class CalculationController {
}
let there be another module - advanced-calculations
which has module commons as a dependency (maven dependency).
Please, note, there are two maven modules on purpose.
So CalculationController is available in other modules that use commons dependency.
Now, let me have two tests in advanced-calculations. (Again, I decided to test CalculationController) in another module.
I know that it is better to have tests in the module that actually defines a component, but commons module was written by other team long time ago; and for now we have to use it.
I want to make sure if we update version of commons, the app should not break (API should not change). Therefore, I added integration tests for CalculationContrioller into advanced-calculation module.
#SpringBootTest(classes = [AdvancedCalculationApplication.class],properties = ["calculatorEnabled=true" ])
#AutoConfigureMockMvc
AdvancedCalculationsITTest extends Specification {
}
and
#SpringBootTest(classes = [AdvancedCalculationApplication.class],properties = ["calculatorEnabled=" ])
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
#AutoConfigureMockMvc
AdvancedCalculationsITTestsDisabled extends Specification {
}
mvn clean install fails because AdvancedCalculationsITTest fails. Error cannot autowire CalculationController because there is no candidate calculationService.
However, when I change slightly order of annotations, it works
#ConditionalOnBean(CalculationService.class)
#RequestMapping(value = "/calculations", produces = MediaType.APPLICATION_JSON_VALUE)
#RestController
class CalculationController {
}
I will update this answer, but a bit later.
For me TODO.
(I will make a demo and add a link to github and put some code examples).
Your ideas and suggestions are welcome!
I have 2 custom annotations (RUNTIME) on a method: one annotation that makes a method always to throw an exception #Exceptional, another #Catchable that always catches an exception. Let this method return void for simplicity. By placing these annotations in different order, you should get a different result.
#Catchable
#Exceptional
public void processAction() {
// There is nothing that throws an exception.
safeStatement1();
safeStatement2();
safeStatementN();
}
vs
#Exceptional
#Catchable
public void processAction() {
// There is nothing that throws an exception.
safeStatement1();
safeStatement2();
safeStatementN();
}
By having these annotations in different order, the result should be different.

JUnit test is getting executed when it's not supposed to

I am new to JUnit. Following is my class hierarchy where classes at top and bottom of the hierarchy has #Test methods. When I execute whole bunch, ConverterBaseEnquiryTest which is at middle of the hierarchy is also getting executed. (That's my guess because I see exception in surefire reports with this name).
And I am getting initialization errors from ConverterBaseEnquiryTest because it wasn't supposed to be executed. Is there any way to figure out why this is happening?
Following is my hierarchy:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:spring/test-default-context.xml"
})
#TransactionConfiguration( transactionManager="profile.transactionManager", defaultRollback=false )
#Ignore
public class BaseCommonTest extends AbstractTransactionalJUnit4SpringContextTests {
abstract public class ConverterBaseTest<F,T> extends BaseCommonTest {
// ...
}
public class ConverterBaseEnquiryTest<F, T> extends ConverterBaseTest<Enquiry, T> {
// ...
}
public class EnquiryToDvsMedicareRequestConverterTest extends ConverterBaseEnquiryTest<Enquiry, DvsMedicareRequest> {
// ...
}
I think this is because #Ignore annotation is not inheritable, so JUnit will execute tests in subclasses. (Although posting the stacktrace would help us).
This means you will also need to place #Ignore on all subclasses.
Alternatively, to save you from that, you could perhaps use #IfProfileValue (which is inherited) on the base-class to disable the tests. This is a Spring annotation supported by the SpringJUnit4ClassRunner.

Categories

Resources