Spring Boot Integration Test case and check if a method is called - spring

I need to write an Integration Test case . In the whole flow i do have a bean class which has a method. I want to write a test case case to check if that method was called in the test or not.
How can i do that ? Any Suggestions ?

You can use the appropriate methods in Mockito
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
verify(mockObject, atLeast(2)).someMethod("was called at least twice");
verify(mockObject, times(1)).someMethod("was called exactly one time");

Related

Better approach to write Junit5 tests for spring boot application

I created a Test class:
void comp() throws IOException{
Foo foo=new Foo()
String file=readFile("xyz.txt")
Model model=foo.generate(file)
Assert.assertEquals(model.getMapA().size(),0);
Assert.assertEquals(model.getMapB().size(),0);
Assert.assertEquals(model.getListC().size(),10);
}
Is this a good approach to writing the Junit test? I mean all the asserts inside one method. An alternate approach I could think of is to have a setup method that will generate the model class and a separate method for checking the size of each attribute. The class Foo is a controller class in a spring boot application.
I am using Junit5. I also saw that Hamcrest is popular, but the last release was on Jul 09, 2012 Which raises a question should we use it or not
The main problem in your test scenario is when the first assertion fails you do not see results of next assertions, I would recommend to start using AssertJ assertions, in that case your assertions would look like (very basic example though):
Model model=foo.generate(file);
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(model.getMapA()).isEmpty();
softly.assertThat(model.getMapB()).isEmpty();
softly.assertThat(model.getListC()).hasSize(10);
});

Spring Boot : how auto configure works and #JsonTest

I've read some stuff about how auto-configuration works behind the scene (configuration classes with #Conditional, spring.factories inside /META-INF etc...)
Now I'm trying to understand with an example : #JsonTest
I can see this annotation is annotated with things like #AutoConfigureJson
What this #AutoConfigureJson does exactly ? Does it import some configuration classes with beans inside ? How Spring know how to use this annotation (basically this annotation is almost empty and doesn't say which classes to scan)
#AutoConfigure... (like #AutoConfigureJson) annotations are the way to allow tests with multiple "slices".
Slices load into your tests only a subset of the application, making them run faster. Let's say you need to test a component that uses the Jackson Object Mapper, then you would need the #JsonTest slice. (here is the list of all available slices.)
But you may also need some other part of the framework in your test not just tha single slice; let's say the JPA layer. You may want to annotate the test with both #JsonTest and #DataJpaTest to load both slices. According to the docs, this is not supported.
What you should do instead is choose one of the#...Test annotation, and include the other with an #AutoConfigure... annotation.
#JsonTest
#AutoConfigureDataJpa
class MyTests {
// tests
}
Update:
at a certain point while evaluating the annotation, Spring Boot will hit this line and will pass to the method SpringFactoriesLoader.loadFactoryNames() a source, that is the fully qualified name of the annotation (like interface org.springframework.boot.test.autoconfigure.json.AutoConfigureJson for example).
The loadFactoryNames method will do its magic and read the necessary information from here.
If more details are needed, the best thing is to use a debugger and just follow along all the steps.

How to register bean programatically in Quarkus?

I am trying to find a way how to programatically create bean in quarkus DI, but without success. Is it possible in this framework? It seems that BeanManager does not implement the needed method yet.
First, we should clarify what "programatically create bean" exactly means.
But first of all, we should define what "bean" means. In CDI, we talk about beans in two meanings:
Component metadata - this one describes the component attributes and how a component instance is created; the SPI is javax.enterprise.inject.spi.Bean
Component instance - the real instance used in application; in the spec we call it "contextual reference".
The metadata is usually derived from the application classes. Such metadata are "backed by a class". By "backed by a class" I mean all the kinds described in the spec. That is class beans, producer methods and producer fields.
Now, if you want to programatically obtain a component instance (option 2), you can:
Inject javax.enterprise.inject.Instance; see for example the Weld docs
Make use of CDI.current().select(Foo.class).get()
Make use of quarkus-specific Arc.container().instance(Foo.class).get()
However, if you want to add/register a component metadata that is not backed by a class (option 2), you need to add an extension that makes use of quarkus-specific SPIs, such as BeanRegistrar.
If you are looking for Quarkus equivalent of Spring #Configuration then you want "bean producer" (as mentioned in comments above)
Here is an example(koltin) of how to manually register a clock:
import java.time.Clock
import javax.enterprise.context.ApplicationScoped
import javax.enterprise.inject.Produces
#ApplicationScoped
class AppConfig {
#Produces
#ApplicationScoped
fun utcClock(): Clock {
return Clock.systemUTC()
}
}
#Produces is actually not required if method is already annotated with #ApplicationScoped
#ApplicationScoped at class level of AppConfig is also not required
Although, I find those extra annotations useful, especially if are used to Spring.
You can inject your beans using Instance:
#Inject
public TestExecutorService(final ManagedExecutor managedExecutor,
final Instance<YourTask> YourTask) {
this.managedExecutor = managedExecutor;
this.YourTask= YourTask;
}
And if you need to create more than one Instance you can use the managed executor:
tasks.forEach(task -> managedExecutor.submit(task::execute));
Keep in mind that depending on the way you start the bean you may need to destroy it and only the "creator class" has its reference, meaning you have to create and destroy the bean in the same classe (you can use something like events to handle that).
For more information please check: CDI Documentation

Inject code into method with Javassist

I'm trying to add some code to a class that is inside a jar(maven dependecy) and i'm doing it in the following way:
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("xyz.abc.ClassInADependecy");
CtMethod method = ctClass.getDeclaredMethod("getSomeValue");
method.insertBefore("{ System.out.println(\"modified\"); }");
I'm using Spring and the above code is being called using a #Configuration annotation.
When i call the method getSomeValue nothing is printed.
Can you help me find out what i'm doing wrong?
Thank you very much.
You are only changing the implementation as it is represented in Javassists type pool. You have to make sure that the class is also loaded by the respective class loader. Also, this must happen before the class is loaded for the first time, i.e. before your Spring application loads that class.
One way to do so is to manipulate the class from a Java agent: https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html

Using Spring Framework's #Autowired for instantiating and injecting SUT (System Under Test) in the test fixture

I have seen developers using Spring's #Autowired feature making Spring framework responsible for instantiating and injecting SUT (System Under Test) or CUT (Class Under Test) in the test class or fixture. The following is the snippet showing #Autowired being used in the test fixture:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.ExpectedException;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.springframework.test.context.ContextConfiguration;
interface BackingStore
{
//Some methods
}
class Logger
{
public Logger(BackingStore backingStore)
{
//Capture input parameter into member variables
}
public void Log(String message)
{
//Some logic
}
}
#ContextConfiguration(locations = { "classpath:someconfig.xml" })
public class LoggerTests extends AbstractTestNGSpringContextTests
{
#Autowired
private Logger _logger;
#Test
#ExpectedException(NullPointerException)
public void Log_WhenPassedNull_ShouldThrowException()
{
_logger.Log(null);
}
}
All the dependencies (recursively) required by the SUT are specified as part of the Spring configuration XML file. I do not like this approach. I like all the test (unit or integration) to read like a story (I heard Kent Beck saying the same thing :)). I like instantiating SUT/CUT in the test case itself even though if it is complex. This gives a clear picture about the test case.
I have few concerns regarding #Autowired or any auto injection mechanism being used for injecting SUT in the test fixture:
It reduces test code readability. #Autowire appears like magic. Arrange of AAA (Arrange-Act-Assert) moves to XML file from test code.
It reduces test code maintainability. This is because of #2.
Could not effectively verify constructor of SUT/CUT throwing exception in exceptional cases. I am not 100% sure about this. I do not know if Spring framework has an answer for this.
It seems overkill for unit or integration tests.
I ask experts for 2 cents on this subject.
Thanks.
It only reduces test code readability if you dont know where to look for the #Autowired objects. I would advise using SpringJunitTestRunner that defines the test application context at the top of the unit test class.
Using dependency injection in your test cases allows you to easily test with different objects.
E.g. If your code required a 3rd party service, you could use dependency injection (e.g. Autowiring a Spring bean) to inject a mocked service for your unit tests and the real service for the application.
So for this reason it definitley doesnt decrease the test code maintainability, as it is really encouraging loose coupling between the code youre testing and any external objects.
It may be overkill to inject all objects in such a way, but it is definitely not overkill for unit tests/integration tests in general.

Resources