How to use #Autowire when using #ParameterizedTest in Junit5 - junit5

I currently use SpringBoot1.5 and Junit5.
How do I use #autowire to dependency injection when I use the annotation #ParameterizedTest for parametric testing because I need to interact with the database.
I try to use
TestContextManager testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
but it will cause the #transaction to be unavailable.
this my code
#ExtendWith(MockitoExtension.class)
#RunWith(SpringRunner.class)
public abstract class AbstractUnitTest {
}
public class PatientFacadeTestParameterized extends AbstractUnitTest {
...
#Autowired
PatientFacade patientFacade;(is null)
...
#Transactional
#ParameterizedTest(name = "{index}: {0}")
#YamlFileSource(resources = {"logistics/patient_facade.yaml"})
public void testCreateAccountPhonePatienta(PatientFacadeData patientFacadeData) {
...
patientFacade.createAccountPhonePatient(patientForm1);
...
}
...
I just want to use #ParameterizedTest to manage my input.

Spring Boot 1.5.x depends on Spring Framework 4.3.x, but the latter does not provide built in support for JUnit Jupiter (a.k.a., JUnit 5).
So, if you want to use Spring Framework 4.3.x with JUnit Jupiter, the only option is to use my spring-test-junit5 project.
Once you have configured the dependency on spring-test-junit5, you will have access to the SpringExtension for JUnit Jupiter. This replaces the SpringRunner for JUnit 4.
You should then be able to rewrite your test class in a manner similar to the following. I cannot provide you an exact working example, since I do not have access to the types in your project.
#ExtendWith(SpringExtension.class)
#ExtendWith(MockitoExtension.class)
public class PatientFacadeTestParameterized {
#Autowired
PatientFacade patientFacade;
#Transactional
#ParameterizedTest(name = "{index}: {0}")
#YamlFileSource(resources = {"logistics/patient_facade.yaml"})
public void testCreateAccountPhonePatienta(PatientFacadeData patientFacadeData) {
// ...
patientFacade.createAccountPhonePatient(patientForm1);
// ...
}
What is responsible for injecting the PatientFacadeData into your test method? Does #YamlFileSource take care of that?
By the way, you should practically never need to use the TestContextManager directly in your tests. The SpringRunner and SpringExtension handle that for you.

Related

Can we access spring bean in Karate feature?

I have a class like below, can I access the myServer object or call handleOperation() method (which can use the injected bean) in Karate Feature file? If yes then may I know how?
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {MyApiApp.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = {AcceptanceTestConfiguration.class})
#ActiveProfiles("test")
#KarateOptions(features = "classpath:acceptanceTest/api/myapi.feature", tags = "#myapi")
public class MyAtddTest {
#Autowired
private MyServer myServer;
public void handleOperation() throws Exception {
myServer.handle();
}
}
There is no direct support for spring or the annotations. And not sure if you can mix the test annotations.
But take a look at the Spring MVC Dispatcher example here: https://github.com/intuit/karate/tree/master/karate-mock-servlet#mocking-your-servlet
Specifically how using Java interop you can do anything you want. I recommend getting the spring context using first-principles. For e.g:
ApplicationContext context = new AnnotationConfigApplicationContext(AcceptanceTestConfiguration.class);
And then getting beans out of it. Setting a test profile via System.setProperty() should be simple, search for it. You can do all this in even the karate-config.js and then it should be easy to use from all Scenario-s.
EDIT - also refer: https://github.com/Sdaas/hello-karate

Spring AOP in different projects does not work

I am new to Spring AOP and AspectJ but the simplicity they can provide makes me want to use them.
The questions is: I have two projects, one is a spring boot application server and the other one contains all the utilities functions core. I want to implement logging aspect in both projects and here is what I did:
server
#Aspect
#Component
public class MethodLoggingAspect {
#Around("#annotation(logExecutionTime)")
public Object methodLog(ProceedingJoinPoint joinPoint, LogExecutionTime logExecutionTime) throws Throwable {
final Logger logger = LoggerFactory.getLogger(joinPoint.getTarget().getClass());
final long start = System.nanoTime();
Object proceed = joinPoint.proceed();
final long end = System.nanoTime();
logger.info("method={}, millis={}", joinPoint.getSignature().toShortString(), TimeUnit.NANOSECONDS.toMillis(end - start));
return proceed;
}
}
#Configuration
#EnableAspectJAutoProxy
#ComponentScan
public class BeanConfiguration {
}
core
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface LogExecutionTime {
}
I use the annotation LogExecutionTime both in core and application server these are two different jars and server has dependency core. I expect the aspect will work in both two parts when I run server, but the fact is that only methods in server have the aspect weaved in.
I also tried to define the aspect in core and use aspectJ to do compile-time weaving. But there is Immutable library in core, which will throw a compile time error when I use aspectj-maven-plugin.
Can anyone help me with it? Thanks!

Interceptor on super method in CDI 1.0/JEE6

In the following case,
public class Base {
#Transactional
public void doSave() {
// ...
}
}
public class Inherited extends Base {
public void someMethod() {
super.doSave();
}
#Override
public void doSave() {
super.doSave();
}
}
If I add the #Transactional annotation to Inherited.someMethod, the interceptor gets called without issue.
However, without the annotation on the inherited class, the interceptor does not get involved in the call to the super class from Inherited.someMethod().
Furthermore, calling Inherited.doSave() does not seem to get the interceptor invoked either. I would have expected the annotation on the superclass to be also valid on the subclass. Is this not the expected behaviour?
I am using Apache DeltaSpike for the #Transactional annotation and this is being deployed as a war in an ear (technically as a jar in a war in an ear). However, this may not be relevant as trying with a custom interceptor shows the same behaviour.
This is JBoss EAP 6.3.0 Alpha in case its relevant.
This is expected. Interceptors are only applied if the object is managed. When you you write it this way with inheritence, it's not applied as it's not part of a call stack that CDI is aware of. You would need to inject Base into your class and call Base.doSave

How JUnit TestCase functionality actually works?

I have a code like this:
public class MyTest extends TestCase {
private MyObject mObject1;
private MyObject mObject2;
...
#Override
public void setUp() throws Exception {
super.setUp();
}
public void testSomething() {
mObject1 = new MyObject();
mObject2 = new MyObject();
}
public void testSomething2() {
// Here I can't access the previously created objects mObject1 and
// mObject2, because they are again null.
// Why is that, if *my* setUp() method doesn't touch them?
}
My guess is that JUnit instantiates the class again every time. Can someone please explain me the workflow?
Thanks.
JUnit will instantiate the class (MyTest) once per test and then execute the methods
setUp()
testXXX()
tearDown()
until it runs all the methods that start with test and don't receive any parameters. So in your example, Junit will instantiate MyTest twice. You can read more about this in the JUnit documentation.
Bear in mind that this is the old way of writing tests. From Junit 4 (I think) the preferred way is to use annotations. You can check the annotations documentation here.
As a side note, NUnit, reuses the instance of the test, so in the same scenario, it would only instantiate MyTest once.
JUnit will instantiate this class once per test method, so only once in the code above, but try it again with two test methods and you will see it instantiated twice. If you want to save some state in fields without having to use statics, take a look at TestNG, which reuses the same instance for all test methods.

wicket and AtUnit

I've started playing with Wicket and I've chosen Guice as dependency injection framework. Now I'm trying to learn how to write a unit test for a WebPage object.
I googled a bit and I've found this post but it mentioned AtUnit so I decided to give it a try.
My WebPage class looks like this
public class MyWebPage extends WebPage
{
#Inject MyService service;
public MyWebPage()
{
//here I build my components and use injected object.
service.get(id);
....
}
}
I created mock to replace any production MyServiceImpl with it and I guess that Guice in hand with AtUnit should inject it.
Now the problems are:
AtUnit expects that I mark target object with #Unit - that is all right as I can pass already created object to WicketTester
#Unit MyWebPage page = new MyWebPage();
wicketTester.startPage(page);
but usually I would call startPage with class name.
I think AtUnit expects as well that a target object is market with #Inject so AtUnit can create and manage it - but I get an org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main. Can I instruct AtUnit to use application from wicketTester?
Because I don't use #Inject at MyWebPage (I think) all object that should be injected by Guice are null (in my example the service reference is null)
I really can't find anything about AtUnit inside Wicket environment. Am I doing something wrong, am I missing something?
I don't know AtUnit but I use wicket with guice and TestNG. I imagine that AtUnit should work the same way. The important point is the creation of the web application with the use of guice.
Here how I bind all this stuff together for my tests.
I have an abstract base class for all my tests:
public abstract class TesterWicket<T extends Component> {
#BeforeClass
public void buildMockedTester() {
System.out.println("TesterWww.buildMockedTester");
injector = Guice.createInjector(buildModules());
CoachWebApplicationFactory instance =
injector.getInstance(CoachWebApplicationFactory.class);
WebApplication application = instance.buildWebApplication();
tester = new WicketTester(application);
}
protected abstract List<Module> buildModules();
The initialization is done for every test class. The subclass defines the necessary modules for the test in the buildModules method.
In my IWebApplicationFactory I add the GuiceComponentInjector. That way, after all component instantiation, the fields annotated with #Inject are filled by Guice:
public class CoachWebApplicationFactory implements IWebApplicationFactory {
private static Logger LOG = LoggerFactory.getLogger(CoachWebApplicationFactory.class);
private final Injector injector;
#Inject
public CoachWebApplicationFactory(Injector injector) {
this.injector = injector;
}
public WebApplication createApplication(WicketFilter filter) {
WebApplication app = injector.getInstance(WebApplication.class);
Application.set(app);
app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
return app;
}
}