How to exclude #Value annotation from Jacoco code coverage - spring

I have a class in Spring boot where I am using #Value annotation. In the jacoco reports that line is not getting covered. Even after writing tests that cover all other statements, due to #value annotation the code coverage is being shown as only 10%. How can I exclude #value from jacoco code coverage?

Related

#Test annotation of jupiter not working properly

I have written test cases. Initially I have used junit 4 but now I shifted to junit 5.
I have added and removed ralevant dependency but it not working properly.
My contract test work with junit 4 #Test annotation but same test case not working with Junit 5 #Tesy annotation
I have change relevant part as well.
Because of security I'm not able to share my code.

Kotlintest with Spring Test, #Transactional not working/applied

I have a problem getting Spring Boot 2.0.5 to work nicely with Kotlintest 3.1.10.
I made a test project illustrating the problem I have.
The project is a Spring Boot 2 application
with two entities, ShoppingOrder and OrderLine (to be totally unimaginative).
There is also a test case ShoppingOrderSpec which just tests the mapping by storing and retrieving the Order.
The testcase is configured like this:
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
class ShoppingOrderSpec : WordSpec() {
override fun listeners() = listOf(SpringListener)
The test case is using the SpringExtension
by Spring to hook into the JUnit 5 engine. It also uses the SpringListener and Wordspec from Kotlintest to structure the tests
and do the assertions.
The SpringListener correctly autowires the dependencies, but somehow the transaction is not being created.
Running the testcase gives the following stack-trace:
2018-10-12 10:54:14.329 INFO 59374 --- [intest-engine-0] com.example.demo.ShoppingOrderSpec : Started ShoppingOrderSpec in 4.478 seconds (JVM running for 7.421)
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.demo.ShoppingOrder.lines, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
...
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:35)
at com.example.demo.ShoppingOrderSpec$1$1.invoke(ShoppingOrderSpec.kt:19)
So, somehow the org.springframework.transaction.annotation.Transactional annotation does not seem to work,
as removing the annotation, just gives the same response.
Anyone any ideas how to get the #Transactional being applied and respected?
You can't use JUnit Jupiter extensions with KotlinTest as they are different engines. Junit Jupiter is an implementation on top of Junit Platform, like KotlinTest is, but anything written specifically for Jupiter won't work with KotlinTest. Anything written for Junit Platform should work however.
Unfortunately, the naming choices by the JUnit team are poor imo, and so people think JUnit Jupiter is the same thing as JUnit Platform.
Anyway, those
#ExtendWith(SpringExtension::class)
#Transactional
#SpringBootTest
extensions are not going to mean anything to KotlinTest, anymore than they would for Spek or whatever. ExtendWith is a Jupiter specific annotation that tells it to use the SpringExtension class. The KotlinTest equivilent is SpringListener which you've already wired in.
I'm not sure if #SpringBootTest will be picked up or not by Spring. Support may need to be added for that depending on what it does.
Finally #Transactional works by creating proxies on the methods, but since in more advanced testing frameworks like KotlinTest, the test containers are not methods, but just arbitrary functions, it won't be able to intercept.
I think in this case, you might need to create a proper method and annotate that, or try using the AnnotationSpec rather than StringSpec or whatever other spec base class you are using, which uses actual methods that you could annotate.

Simple #Configurable with modern spring-boot + gradle

My goal is to get a bare bones aspectj+spring aop setup such that I can use #Configurable on one class. One additional restriction is that it needs to use load-time weaving as Lombok doesn't work with CTW.
The good news: I have it working!
The bad news: The console is flooded with [Xlint:cantFindType] errors. See results section below.
The Environment
I have a single class annotated with #Configurable. It is a class used by and instantiated by Jackson, hence the need for AOP. It's not very interesting so I won't show it here. It's just a normal class with the single annotation of Configurable, and an #Autowired bean inside.
SpringBootApplication
My Application class has the usual annotations:
#SpringBootApplication
#EnableSpringConfigured
#EnableLoadTimeWeaving
public class MyApplication {
build.gradle
My build.gradle has all the usual suspects. Sample:
configurations {
springinstrument
}
dependencies {
compile('org.projectlombok:lombok')
compile('org.springframework.boot:spring-boot-starter-aop')
compile("org.springframework.boot:spring-boot-starter-data-rest")
compile('org.springframework.data:spring-data-rest-hal-browser')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-security')
compile('org.springframework.boot:spring-boot-starter-web')
compile('org.springframework.boot:spring-boot-devtools')
compile('org.springframework.plugin:spring-plugin:1.2.0.RELEASE')
..snip..
runtime('org.springframework:spring-instrument:4.+')
springinstrument "org.springframework:spring-instrument:4.+"
runtime configurations.springinstrument.dependencies
}
test.doFirst {
jvmArgs "-javaagent:${configurations.springinstrument.asPath}"
}
jvm args
I am running a JUnit test with the following args (via Intellij's run config)
-ea
-javaagent:/Users/me/.gradle/caches/modules-2/files-2.1/org.springframework/spring-instrument/4.3.3.RELEASE/5db399fa5546172b9c107817b4abaae6b379bb8c/spring-instrument-4.3.3.RELEASE.jar
aop.xml
I have a src/main/resources/META-INF/aop.xml containing:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-Xreweavable -showWeaveInfo">
<!-- only weave classes with #Configurable interface -->
<include within="#org.springframework.beans.factory.annotation.Configurable */>
</weaver>
</aspectj>
However, my suspicion is that this file is not being picked up. It doesn't matter what I put in the file, the results are always the same. Even if I put random non-valid XML.
The Test
The junit test is a simple Jackson serialize-deserialize test using the #Configurable annotated class.
The test class has the annotations:
#SpringBootTest
#RunWith(SpringRunner.class)
The Results
When running a junit test via Intellij -> It Works, but..
The LTW is actual working and my test is passing when run via Intellij with the jvm args above.
However the boot time of the app is significantly longer and the log is flooded with Xlint:cantFindType errors
Example:
2016-11-07 19:28:21.944 INFO 45213 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
[AppClassLoader#18b4aac2] error can't determine implemented interfaces of missing type org.springframework.security.ldap.authentication.LdapAuthenticationProvider
when weaving type org.springframework.security.config.annotation.authentication.configurers.ldap.LdapAuthenticationProviderConfigurer
when weaving classes
when weaving
[Xlint:cantFindType]
[AppClassLoader#18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes
when weaving
[Xlint:cantFindType]
[AppClassLoader#18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes
when weaving
[Xlint:cantFindType]
[AppClassLoader#18b4aac2] error can't determine implemented interfaces of missing type io.undertow.server.handlers.accesslog.AccessLogHandler
when weaving type org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory
when weaving classes
when weaving
[Xlint:cantFindType]
.. many more.. all in the org.springframework.boot package
When running a test via gradle command line -> works, sort of.
When I run the test with gradle test --tests *MyTestClass, the test fails because of a NullPointerException on.. guess what, the #Autowired bean I'm expecting to be injected automatically.
I got it working with gradle test config, huzzah! I've updated the configuration above. But.. it suffers from the same problem as running it in my IDE: the Xlint:cantFindType
So the issues:
The gradle configuration is wrong, so running the app via gradle fails. How do I fix the gradle config?
The Xlint:cantFindType errors. Is the aop.xml not being picked up? How to resolve this?
I have yet to find a simple spring-boot+gradle+ #Configurable sample that uses aop.xml
I solved the problem, and it's rather embarrassing.
It was due to the fact that the aop.xml wasn't being picked up.
The file wasn't being detected because it was in a directory named META_INF/ on the class path, not META-INF/. That's a pretty important difference.
Anyways, I've updated the question with the minimal configuration needed to get #Configurable working with a modern spring-boot and gradle setup with load time weaving for Lombok support. Hopefully it will be useful for someone.

How to speed up unit tests with less configuration

The unit test template of jhipster is great, but sometime, especially, during coding, I need to write unit test code and run frequently. But now the unit test will start tomcat container and many other module, which I don't need if I want to test a service function.
Now the test class is like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
#Transactional
public class SomeClassTest {
.....
How can I modify it to only initialize spring container and DB? Thanks.
If you do not need the server, don't make your test an integration test. If you remove #WebAppConfiguration and #IntegrationTest spring boot will start a regular (i.e. non-web context) and will not start Tomcat.
If you need to go even further, you can disable certain features, either via application-test.properties + #ActiveProfiles("test") to disable stuff via config or using the exclude parameter of #SpringBootApplication (or #EnableAutoConfiguration) as Lukas said already.
Take a look at this question How to exclude *AutoConfiguration classes in Spring Boot JUnit tests? and see if this helps you. The idea is to explicitly exclude auto configurations that you don't need in your test, so in your case it would probably be EmbeddedServletContainerAutoConfiguration

What does this do: #RunWith(SpringJUnit4ClassRunner.class)

What does this annotation do?
When would I want to use it?
When would I not want to use it?
#RunWith(SpringJUnit4ClassRunner.class)
I can find more usages of this when I Google and do not find a 101 explanation as to what this annotation is supposed to communicate to me or when/why I would use it?
The annotation is used to configure a unit test that required Spring's dependency injection.
From Spring Reference - 10. Unit Testing:
10.1 Creating a Unit Test Class
In order for the unit test to run a batch job, the framework must load the job's ApplicationContext. Two annotations are used to trigger this:
#RunWith(SpringJUnit4ClassRunner.class): Indicates that the class should use Spring's JUnit facilities.
#ContextConfiguration(locations = {...}): Indicates which XML files contain the ApplicationContext.
If you are using annotations rather than XML files, then any class that you are unit testing that requires Spring dependency injection needs to be put into the #ContextConfiguration annotation. For example:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = FooManager.class)
class FooManagerTest {
#Autowired
FooManager fooManager;
Now when you use fooManager in a unit test it will have have a Spring context setup for it.
If fooManager autowires in any beans then those bean's classes also need to be in the #ContextConfiguration annotation. So if fooManager autowires in a FooReporter bean:
#ContextConfiguration(classes = {FooManager.class, FooReporter.class})
If the beans that fooManager autowires in contain state, then you will likely want to reset the state of those beans for each test. In that case you can add the #DirtiesContext annotation to your test class:
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
If fooManager or any of its autowired beans reads Spring config then you need to add an initializers list to the #ContextConfiguration annotation, that contains the ConfigFileApplicationContextInitializer class:
#ContextConfiguration(classes = {FooManager.class, FooReporter.class}, initializers = ConfigFileApplicationContextInitializer.class)
To answer the when you would and wouldn't want to use it part of the question.
When to use SpringJUnit4ClassRunner
IMO SpringJUnit4ClassRunner should be used very sparingly. There is a significant overhead involved with starting up a Spring container to run a unit test.
I typically use SpringJUnit4ClassRunner to test:
that components are injected (auto-wired) as expected
that configuration data is injected as expected
When you are injecting components issues can arise if the #Qualifier annotation is not used or used incorrectly, for example.
When loading configuration from multiple yaml files you may want to test that maps are being merged as expected, with the appropriate overrides occurring.
At the very least I always have a simple SpringJUnit4ClassRunner test as a sanity check that the Spring container starts up OK.
When not to use SpringJUnit4ClassRunner
I would not use SpringJUnit4ClassRunner to test the non-Spring related functionality in my code under test. Which in my experience means most of the functionality.
So this means that any autowired components and injected config data needs to be mocked. This can mean quite a bit of setup code for your unit tests. However this setup code only needs to be written once for all the tests in your class under test. It is also much quicker to run unit tests with mocked components.
I keep the mocking simple and use Spock to mock the components. Example groovy code:
import spock.lang.Specification
class FooManagerTest extends Specification {
FooManager cut
void createMockFooReporter() {
FooReporter mockFooReporter = Mock(FooReporter)
mockFooReporter.fooFormatter = Mock(FooFormatter)
}
void setup() {
cut = new FooManager()
cut.fooReporter = createMockFooReporter()
}
void "Basic test"() {
// Do a basic test using 'cut'
}
}
In this example the class under test FooManager has an autowired FooReporter which itself contains an autowired FooFormatter.
I think #RunWith annotation is in order to initialize the context of spring. Because the junit5 is released, you just can replace it with #SpringJUnitConfig.By the way, #RunWith annotation is already replaced by #ExtendWith, but you still can use it.

Resources