JaCoCo maven plugin not covering test for spring boot appplication - spring-boot

I have below method in my springboot application class, which fetch data from DB
public void load(){
Optional<List<Employee>> employee = employeeRepository.findEmployee();
// Some other code with employee data
}
I am writing some Junit 4 Test case for this method and also counting coverage with Jacoco plugin.
#RunWith(MockitoJUnitRunner.class)
public class EmployeeTest{
private EmployeeRepository employeeRepository = Mockito.spy(EmployeeRepository.class);
#Test
public void shouldLoadDataFromDB(){
EmployeeService employeeService = new EmployeeService(employeeRepository);
when(employeeRepository.findEmployee()).thenReturn(buildDataFromDB());
employeeService.load();
// Assertions
}
}
For above I am always getting code coverage 0 even though I have covered test for given method,also shows method is not not covered in test.
Can someone give some idea what am I missing here.
Edit
I have check in jacoco-session.html file, I don't see my classes there. How can I check what I am missing.
JaCoCo documentation saying class Id mismatch will also cause this issue but I don't understand how to check this.
Can you please help me on this.

Related

Spring Boot / Junit5+Mockito: Mock's mockitoInterceptor gets replaced during test?

I have two service classes (there are more, of course, but those two are relevant here), which are in use during an integration test.
For test, I set up a mock (ConfigurationService) and stub two methods:
#ExtendWith(SpringExtension.class)
#ActiveProfiles("test")
#SpringBootTest
#TestPropertySource(properties =
"spring.main.allow-bean-definition-overriding=true")
public class VehicleAuditExecutionServiceIT {
#MockBean
private ConfigurationService configurationServiceMock;
#Autowired
private VehicleAuditExecutionService vehicleAuditExecutionService;
#Test
void testExecuteVehicleAudits() throws IOException {
// quite some DB operations for the test setup here
AuditDurationConfigDTO auditDurationConfigDTO = new AuditDurationConfigDTO();
auditDurationConfigDTO.setMaxDuration(deMaxDuration);
Map<String, ScheduledAuditConfigDTO> map = new HashMap<>();
map.put(country, ScheduledAuditConfigDTO.builder()
.groupCalculationEnabled(false)
.build());
when(configurationServiceMock.getAuditDurationConfig(country)).thenReturn(auditDurationConfigDTO);
when(configurationServiceMock.getScheduledAuditConfigurationForCountry(country)).thenReturn(ScheduledAuditConfigDTO.builder()
.groupCalculationEnabled(false)
.sameAuditDurationAllDealersSameGroupId(false)
.build());
vehicleAuditExecutionService.executeVehicleAudits(startDate, country);
verify(publishAuditInterfaceMock).pushExecutions(country, dealerDe1ExportAuditDtoList, auditCategory);
}
#ComponentScan(basePackages = "com.application")
#SpringBootApplication
#PropertySource("classpath:application-test.yml")
static class TestConfiguration {}
}
After the setup, the stubbings are available:
During the test's execution, vehicleAuditExecutionService.executeVehicleAudits(startDate, country) calls the AuditPreparationService, which in turn uses the configurationServiceMock (using #Autowired constructor injection). As expected, the calls gets matched and result set up is returned.
Later, the execution returns to vehicleAuditExecutionService.executeVehicleAudits(startDate, country), where it calls the configurationServiceMock (#Autowired constructor injection, as well) again. But here, the mock's configuration has been changed: the mock's attribute mockitoInterceptor gets replaced by some other instance.
Result: the stubbing is gone and the call returns null - leading to a NPE.
The screenshots were taken using org.springframework.boot:spring-boot-starter-parent:2.7.6, but I've tried that with multiple Spring Boot versions:
2.7.0
2.6.14
2.5.14
2.4.13
2.3.12.RELEASE
Each version has this issue - but I've never seen it in any other test. So I guess, there's something wrong with my test setup - but I cannot spot it.
Any idea, why this is happening?
Thanks a lot - please do not hesitate to ask for any further information, if needed for analysis.
kniffte

How to perform Tests for DTOs?

I am creating a class to store the tests of all DTO classes, but currently I only manage to cover 10% of the coverage. I need to know how to do the #Tests for the DTOs.
My DTO:
#Data
#NoArgsConstructor
public class ActivityDTO {
private Integer id;
private Integer version;
#JsonProperty("working_days")
private MonthWorkingDays workingDays;
}
My Test class:
#Test
public void ActivityDTOTest() {
ActivityDTO obj = BeanBuilder.builder(ActivityDTO.class).createRandomBean();
}
This is the coverage:
My problem: I don't know how to test the DTO class, I'm testing with assertEquals but I don't know how to apply it. Can someone put what the Test class would be like for this DTO class and thus be able to replicate it in the other classes?
This might be subjective, but in general you should not test to increase the coverage, instead you should always think "what exactly" the test checks.
In a nutshell, there can be two things to be tested:
A state of the object
A behavior
Most of the tests usually (arguably, but at least this is what I usually do in my project) tend to check the behavior that is technically implemented as a business logic inside the methods.
Since the DTOs do not really have methods with the logic, you can only test the state of the object.
Another idea: there is no point in checking the code that you haven't written. So yes, following your example in the question, putting lombok annotations will generate some getters/setters/constructors - but its not your code, the proper handling of these annotations was supposed to be checked by lombok team itself.
What you can do if you really want to test DTOs is generate the one with some default values and check that its internal state indeed matches the expected. Something like this:
public class ActivityDTO {
private Integer id;
private Integer version;
// getters / setters maybe
}
#Test
public void test_state_is_correct() {
ActivityDTO underTest = new ActivityDTO(SAMPLE_ID, SAMPLE_VERSION);
assertThat(underTest.getId(), equalTo(SAMPLE_ID));
assertThat(underTest.getVersion(), equalTo(SAMPLE_VERSION));
}
#Test
public void test_equals_two_objects_with_same_values() {
ActivityDTO underTest = new ActivityDTO(SAMPLE_ID, SAMPLE_VERSION);
assertThat(underTest, equalTo(new ActivityDTO(SAMPLE_ID, SAMPLE_VERSION));
}
#Test
public void test_equals_two_objects_with_different_id() {
ActivityDTO underTest = new ActivityDTO(SAMPLE_ID, SAMPLE_VERSION);
assertThat(underTest, not(equalTo(new ActivityDTO(ANOTHER_SAMPLE_ID, SAMPLE_VERSION));
}
#Test
public void test_equals_two_objects_with_different_version() {
ActivityDTO underTest = new ActivityDTO(SAMPLE_ID, SAMPLE_VERSION);
assertThat(underTest, not(equalTo(new ActivityDTO(SAMPLE_ID, ANOTHER_SAMPLE_VERSION));
}
... test for toString()... and hashCode maybe, etc.
This will make the coverage tool happy for sure, but the real question is will it make your code better (more robust and less buggy, etc)?
One thing for sure - these tests are time consuming, boring, and probably give less value to the project. To overcome the frustration of the programmers who absolutely need to write these tests there are even tools for automatic testing of these simple java beans (DTO can be viewed as a java bean), to name a few:
https://github.com/codebox/javabean-tester
https://code.google.com/archive/p/junit-javabean-runner/
http://javabeantester.sourceforge.net/
Now the entirely different story is if you test the behavior of some service or DAO that, say, generates the DTO - these tests whether they're unit or integration tests are really needed. They'll also increase the coverage of the project (and maybe even will cover the code of the DTO, although its not their primary goal), but I would suggest to start writing these tests first.
I don't know what is the best practice but AFAIK you should exclude the DTO classes from the configuration and you don't have to write unit test for them.
If you are using JaCoCo plugin, you better check this out: How to exclude certain classes from being included in the code coverage? (Java)

spring unit test repository save not working

I'm trying to write a unit test, for my spring server.
First it will check if a username is present or not in repository, if not so the username is available, then it will return true, and then I will save that username to my repository and check if available ot not it should return false.
Here is my code:
#Test
public void availableTest() {
String username="some_username";
LoginCredential lc=new LoginCredential();
lc.setUsername(username);
lc.setPasswordHash("1");
lc.setSessionID(0);
assertEquals(true, loginCredentialService.available(username));
loginCredentialRepository.save(lc);
assertEquals(false, loginCredentialService.available(username));
}
But for some reason, for the last assertEquals it gives me error. So I can say, the data is not being saved in repository, as I have tested my APIs using postman.
So how this can be resolved?
I think testing class is properly annotated:
#RunWith(SpringRunner.class)
#SpringBootTest
public class MainApplicationTests {
#Autowired
private LoginCredentialService loginCredentialService;
#MockBean
private LoginCredentialRepository loginCredentialRepository;
...
You tagged the OP with H2, so I guess you know about In-Memory databases.
If you use the #SpringBootTest annotation, you are writing an integration test, so you'll test the full application as wired by Spring. For efficiency you might want to use an in-memory database for testing instead of a full SQL Server.
You can achieve this by adding H2 database as a test dependency, which will be picked up by Spring Boot for integration test repositories. Then you can inject the actual repository:
#Autowired
private LoginCredentialRepository loginCredentialRepository;
Additionaly, you can make your test #Transactional. Then every test case will run in a separate transaction, and the transaction will be rolled back after every test, so you don't need to worry about cross-test polution.
If you just want to Unit Test the LoginCredentialService, you need to stub the relevant methods on the repository, e.g.
#MockBean
private LoginCredentialRepository loginCredentialRepository;
#Test
public void availableTest1() {
when(loginCredentialRepository.existByName(username)).thenReturn(true);
assertEquals(false, loginCredentialService.available(username));
}
#Test
public void availableTest2() {
when(loginCredentialRepository.existByName(username)).thenReturn(false);
assertEquals(true, loginCredentialService.available(username));
}
You can do this as a pure Mockito test, too, without #SpringBootTest.

Retrieve and Modify the #ConfigurationContext programmatically via code?

How to Retrieve and Modify the #ConfigurationContext programmatically via code ?
I have a default configuration where it contains valid xml files.
Now i need to add an invalid configuration for a particular test case and test the same.
How to override, retrieve and modify the #ConfigurationContext programmatically via code ?
Thanks in advance,
Kathir
Disclaimer: I am assuming you are using JUnit since you didn't comment differently in your reply to my comment.
I think what you are trying to do does not make lot of sense, in my opinion it is still better to create a dedicated test class for your not-working configuration in order to be able to do more than one test. However:
annotate your test class with #RunWith(SpringJUnit4ClassRunner.class) and #ContextConfiguration(locations = {"classpath:/working-context.xml"}). In this way you can retrieve the configuration context in two ways: first, you can simply declare a field #Inject ApplicationContext context which will contain the working context. Or, you make your test class implements ApplicationContextAware and then write a public void setApplicationContext (ApplicationContext applicationContext). I would go for the second one since it will come in hand for changing the context programmatically.
write a not-working-context.xml and place it in your classpath
in the test method you want to fail, reload the application context with context = setApplicationContext(new ClassPathXmlApplicationContext("not-working-context.xml")); and test all the errors you like.
though it is not good practice to stand on test case order, make sure your failing test will be executed as the last one (tests are executing alphabetically) so you don't have to reload the working context in the other tests.
In the end your test class will look like:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath:/working-context.xml"})
public class TestClass implements ApplicationContextAware {
private ApplicationContext context;
public void setApplicationContext(ApplicationContext context){
this.context = context;
}
//Other tests
#Test
public void zFailingTest() {
context = setApplicationContext(new ClassPathXmlApplicationContext("not-working-context.xml"));
//your test
}
}

junit 4 TransactionalTestExecutionListener insert test data only once for all tests in class?

I have a junit 4 test class testing a DAO.
unit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:/WEB-INF/applicationContext-db.xml",
"classpath:/WEB-INF/applicationContext-hibernate.xml",
"classpath:/WEB-INF/applicationContext.xml" })
#TestExecutionListeners({DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
#DataSetLocation("test/java/com/yada/yada/dao/dbunit-general.xml")
#TransactionConfiguration(transactionManager="transactionManager", defaultRollback = true)
#Transactional
public class RealmDAOJU4Test {
#Autowired
private DbUnitInitializer dbUnitInitializer;
#Autowired
private RealmDAO realmDAO;
#BeforeTransaction
public void setupDatabase() {
// use dbUnitInitializer to insert test data
}
#Test
public void testGetById() {
Integer id = 2204;
Realm realm = realmDAO.get(id);
assertEquals(realm.getName().compareToIgnoreCase(
"South Technical Realm"), 0);
assertEquals(8, realm.getRealmRelationships().size());
}
// more test methods annotated here
}
The #BeforeTransacation method runs before EVERY test method. What I would like to do is: use my DbUnitInitializer to load data into my database - ONCE when the class is created. Then have each test in the class do what it needs to do with the database, then roll back (not commit) it's changes. It seems over kill to re-insert all the same data from my test files before EVERY test. Is there a way to accomplish this?
or
Is the correct way to write these tests to completely load the database before EVERY test? If so, what function does the defaultRollback=true have in this situation?
thanks for helping me along in my thinking...
You need to use a TestExecutionListener and set up your database in the beforeTestClass method. See the Annotations section of the Testing chapter in the Spring user guide.

Resources