TestNG groups with custom SpringContext - kotlin

I am doing a refactoring of my entire test suite by grouping the different test types into multiple groups ( unittest, integration test ...tests).
TestNG allows you to do that with the groups annotation like below
#Test(groups = [ "integrationTest" ])
class MyGroupedTest : MySprpingTestClass() {
private lateinit var myVar: MyVarService
#Autowired
private lateinit var myRepo: MyRepo
#Autowired
#Named("requires_new")
lateinit var txTemplate: TransactionTemplate
I encounter that when adding the group to my Test class, TestNg throughs does not loads my SpringApplicationContext and claims that MyRepo dependency is not initliazed
The following link redirects me to
But I do not see how does it translate to my problem.
Note that my class is inheriting from a base class which bootstraps a small Spring application with few beans and a connection to database with not issues

Related

Null controller when test with Mockito

I'm testing a controller that needs a Autowired Service.
I read in many place (example Mockito: How to test my Service with mocking?) I need to do it like this
#RunWith(JUnitPlatform.class)
public class AdminControllerTest {
#Mock
private AdminService service;
#InjectMocks
private AdminController adminController;
#Test
public void registerUser() {
Boolean resultReal = adminController.registerUser();
assertTrue(resultReal);
}
}
But it's fail and I see is because the adminController is null
Instead, if I create the controller like this
AdminController adminController = new AdminController();
It works, but then I can inject the mock.
Maybe I'm forgotten something
Per the documentation for InjectMocks:
MockitoAnnotations.openMocks(this) method has to be called to initialize annotated objects. In above example, openMocks() is called in #Before (JUnit4) method of test's base class. For JUnit3 openMocks() can go to setup() method of a base class. Instead you can also put openMocks() in your JUnit runner (#RunWith) or use the built-in MockitoJUnitRunner.
Thus, either:
call openMocks(this) somewhere before the test is run or
Use #RunWith(MockitoJUnitRunner.class) on the class

How to use #Autowire when using #ParameterizedTest in 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.

How do you mock a singleton dependency in JMockit?

I'm working on some automated unit and integration tests for a robot. As you could imagine, a robot has a lot of sensor objects and such that would need mocking during testing.
One of the dependencies is a singleton designed not to be instantiated by anything but itself. As I understood it (I'm new to JMockit), once a class is annotated with #Mocked all of its methods and constructors are mocked. JMockit Documentation:
There are three different mocking annotations we can use when declaring mock fields and parameters: #Mocked, which will mock all methods and constructors on all existing and future instances of a mocked class
However I'm noticing (via the usage of a breakpoint) that the real class' constructor is being called and failing to access a sensor, causing the tests to fail.
Here is the relevant part of the singleton I'm trying to mock. Note that I cannot modify this class:
public class DriverStation() {
// This line in particular is an issue.
private static DriverStation currentInstance = new DriverStation();
public static DriverStation getInstance() {
return DriverStation.instance;
}
private DriverStation() {
// This constructor cannot be called during tests.
}
}
And here is my test code:
public class BlingControllerTest {
#Mocked
private DriverStation station;
#Tested
private BlingController blingController;
/**
* Tests getting the robot's operation period while not in a real match.
*/
#Test
public void testGetOperationPeriodDuringRealMatch(#Mocked DriverStation station) {
new Expectations(DriverStation.class) {{
DriverStation.getInstance();
result = station;
station.isFMSAttached();
result = true;
station.isAutonomous();
returns(true, false);
}};
}
}
Full source also available on GitHub
I should also mention that for some reason calling the singleton's constructor locally during tests isn't a problem, but when the tests are run on travis-ci it is a problem.
Stacktrace from running on travis-ci:
ca.team2706.frc.robot.commands.bling.BlingControllerTest > testGetOperationPeriodDuringRealMatch STANDARD_ERROR
java.io.IOException: wpiHaljni could not be loaded from path or an embedded resource.
attempted to load for platform /linux/x86-64/
at edu.wpi.first.wpiutil.RuntimeLoader.loadLibrary(RuntimeLoader.java:79)
at edu.wpi.first.hal.JNIWrapper.<clinit>(JNIWrapper.java:25)
at edu.wpi.first.wpilibj.DriverStation.<init>(DriverStation.java:194)
at edu.wpi.first.wpilibj.DriverStation.<clinit>(DriverStation.java:132)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:398)
at mockit.internal.state.TestRun.ensureThatClassIsInitialized(TestRun.java:138)
at mockit.internal.expectations.mocking.BaseTypeRedefinition.redefineType(BaseTypeRedefinition.java:65)
at mockit.internal.expectations.mocking.TypeRedefinition.redefineType(TypeRedefinition.java:28)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:78)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldType(FieldTypeRedefinitions.java:65)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.redefineFieldTypes(FieldTypeRedefinitions.java:53)
at mockit.internal.expectations.mocking.FieldTypeRedefinitions.<init>(FieldTypeRedefinitions.java:33)
at mockit.integration.TestRunnerDecorator.handleMockFieldsForWholeTestClass(TestRunnerDecorator.java:142)
at mockit.integration.TestRunnerDecorator.updateTestClassState(TestRunnerDecorator.java:40)
Any and all help is appreciated.

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

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;
}
}