Mock CDI Injected class using Mockito on a JUnit test - java

This is the method that i am trying to test:
#Singleton
public class PriorityJobQueueService {
public void registerIndividualJob(String jobCode) throws InterruptedException {
List<PriorityJobMapDTO> priorityJobMapDTOS = CDI.current().select(JobGroupsMasterService.class).get().getJobForCronScheduler(jobCode);
priorityJobMapDTOS = validateStrictJobs(priorityJobMapDTOS);
triggerJob(priorityJobMapDTOS);
}
}
This is the skeleton structure of my test file:
#RunWith(MockitoJUnitRunner.class)
public class PriorityJobQueueServiceTest {
#Before
public void beforeTest() throws Exception {
fixture = new Fixture();
}
#Test
public void registerIndividualJob_SUCCESS() throws InterruptedException {
}
private class Fixture {
#InjectMocks
PriorityJobQueueService priorityJobQueueService;
private Fixture() throws Exception {
MockitoAnnotations.initMocks(this);
}
}
}
Now, what i need to do is mock CDI.current.select() statement so that i can run the test.
The only things i've found so far is having to add additional dependencies to my project with the following libraries:
Quarkus
cdi-unit
So are there any other ways to achieve this?

I would change the code to be composable. That's the entire point of Dependency Injection :)
#Singleton
public class PriorityJobQueueService {
#Inject
private JobGroupsMasterService jobGroupsMasterService;
public void registerIndividualJob(String jobCode) throws InterruptedException {
List<PriorityJobMapDTO> priorityJobMapDTOS = jobGroupsMasterService.getJobForCronScheduler(jobCode);
priorityJobMapDTOS = validateStrictJobs(priorityJobMapDTOS);
triggerJob(priorityJobMapDTOS);
}
}
Now your test will look like
#RunWith(MockitoJUnitRunner.class)
class PriorityJobQueueServiceTest {
#Mock
private JobGroupsMasterService jobGroupsMasterService;
#InjectMocks
private PriorityJobQueueService priorityJobQueueService;
#Test
void registerIndividualJob_SUCCESS() throws InterruptedException {
priorityJobQueueService.registerIndividualJob(...);
}
}
cheers, good luck!

Related

Why does my Unit Test keep saying NullPointerException? I'm using #BeforeClass and it doesn't seem to work

public class FlooringMasteryServiceLayerImplTest {
private FlooringMasteryServiceLayer service;
/*public FlooringMasteryServiceLayerImplTest() {
ApplicationContext ctx
= new ClassPathXmlApplicationContext("applicationContext.xml");
service
= ctx.getBean("serviceLayer", FlooringMasteryServiceLayer.class);
}*/
#BeforeClass
public static void setUpClass() {
}
#AfterClass
public static void tearDownClass() {
}
#Before
public void setUp() {
}
#After
public void tearDown() {
}
#Test
public void testCreatedOrderFileNameFromDate() {
LocalDate date = LocalDate.parse("2020-11-25");
String orderFileName = service.createOrderFileNameFromDate(date);
assertEquals(orderFileName, "Orders_11252020.txt", "The order file name generated was incorrect.");
}
}
I can't seem to find what the solution is for this Failed Unit Test. I have #BeforeClass so I believe it is running JUnit4. It just keeps saying NullPointerException and I don't know how to solve this issue. Please help
You need to initialize your variable "service" inside #BeforeClass method.

Testing for class field with is share among methods

I have a Java class as follow
public class MyClass {
private final ShowFactory showFactory;
private SomeShow someShow;
public MyClass(ShowFactory showFactory) {
this.showFactory = showFactory;
startShow();
}
public void startShow() {
someShow = showFactory.createShow();
someShow.start();
}
public void showSomething() {
MagicBox magicBox = new MagicBox();
someShow.showSomething(magicBox);
}
public void stopShow() {
someShow.stop();
}
}
and trying to test showSomething method. Complete test file is as follow
public class MyClassTest {
private ShowFactory showFactory;
private SomeShow someShow;
#Before
public void setUp() {
showFactory = mock(ShowFactory.class);
someShow = mock(SomeShow.class);
when(showFactory.createShow()).thenReturn(someShow);
}
#Test
public void shouldStartShow() {
new MyClass(showFactory);
verify(someShow).start();
}
#Test
public void shouldShowSomething() throws Exception {
MagicBox magicBox = mock(MagicBox.class);
PowerMockito.whenNew(MagicBox.class).withAnyArguments().thenReturn(magicBox);
doNothing().when(someShow).showSomething(magicBox);
InOrder inOrder = inOrder(someShow);
MyClass myClass = new MyClass(showFactory);
myClass.showSomething();
inOrder.verify(someShow).start();
inOrder.verify(someShow).showSomething(magicBox);
}
#Test
public void shouldStopShow() {
MyClass myClass = new MyClass(showFactory);
myClass.stopShow();
verify(someShow).start();
verify(someShow).stop();
}
}
But test shouldShowSomething is failing with error Wanted but not invoked. Any thing I am missing here? Any suggestion?
It was simple fix. After reading through https://github.com/powermock/powermock/wiki/MockConstructor#quick-summary (thanks to #roby) turns out I was missing the #PrepareForTest annotation for the class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
...
}

Error: Static mocking is already registered in the current thread

Junit test case getting failed:
existing static mocking registration must be deregistered
Test class:
#RunWith(MockitoJUnitRunner.class)
public class DeleteReportServiceTest {
#InjectMocks
private ReturnCheckController returnCheckController;
#Mock
MockedStatic<DigitalGatewayRESTClient> mockDigiGateway;
#Before
public void setUp() throws Exception {
this.returnCheckController = new ReturnCheckController();
this.mockDigiGateway = Mockito.mockStatic(DigitalGatewayRESTClient.class);
}
#Test
public void testdeleteReport() throws Exception {
String input = "{\"clientId\": \"1\", \"applicationId\": \"9010\"}";
String response = "{\"success\":true,\"successText\":\"Manual adjustment record deleted\"}";
String expected = "{\"status\":200}";
JSONObject returnJson = new JSONObject(response);
mockDigiGateway.when((Verification) DigitalGatewayRESTClient.getDGRESTConnection(Mockito.any())).thenReturn(returnJson);
String actual = returnCheckController.deleteReport(input);
Assert.assertNotNull(actual);
Assert.assertEquals(expected, actual);
}
#After
public void after() {
mockDigiGateway.close();
}
}
Closing the static mocking still am getting the error.
You can NOT use #Mock and MockedStatic at same time.
Instead, if you want to stub static method of DigitalGatewayRESTClient, you should create a MockedStatic<DigitalGatewayRESTClient> additionally, like this:
private MockedStatic<DigitalGatewayRESTClient> mockedStaticDigiGateway;
Then initialize mockedStaticDigiGateway:
#Before
public void setUp() throws Exception {
this.mockedStaticDigiGateway = Mockito.mockStatic(DigitalGatewayRESTClient.class);
// other setup...
}
and modify your test case, stub mockedStaticDigiGateway.when... instead:
#Test
public void testdeleteReport() throws Exception {
// arrange ...
mockedStaticDigiGateway.when((Verification) DigitalGatewayRESTClient.getDGRESTConnection(Mockito.any()))
.thenReturn(returnJson);
// assert...
}
Finally, close mockedStaticDigiGateway after test is finished:
#After
public void after() {
mockedStaticDigiGateway.close();
}
I think it will work correctly although one year passed.

Apache camel Junit mock issue

I am writing a JUnit test case for a Route class. I'm facing a problem while mocking ServiceClass inside the Processor class.
public class SaveRouteTest extends CamelTestSupport {
private Exchange exchange;
protected ProducerTemplate template;
private SaveRequestBuilder saveRequestBuilder;
private SaveRoute route;
private SaveProcessor saveProcessor;
private ApplicationContext springContext = createApplicationContext();
#Mock
SaveServiceClient saveServiceClient;//Not able to mock this class
#BeforeClass
public void prepareTestCamelContext() throws Exception {
route = springContext.getBean("saveRoute", saveRoute.class);
saveProcessor = springContext.getBean("saveProcessor",
SaveProcessor.class);
saveRequestBuilder = springContext.getBean("saveRequestBuilder",
SaveRequestBuilder.class);
}
#BeforeMethod
public void init() throws SQLException, ServiceException {
MockitoAnnotations.initMocks(this);
exchange = new DefaultExchange(context);
}
#Override
protected RouteBuilder[] createRouteBuilders() throws Exception {
template = context.createProducerTemplate();
return new RouteBuilder[]{route};
}
#Test
public void testHotelCommitTransactionRouteSuccessReturn() throws
Exception {
when(saveServiceClient.invokeServiceWithName(anyObject()).
thenReturn("Response");
exchange.getIn().setBody("Request detail");
exchange = template.send("direct:SaveRoute",exchange);
}
protected ApplicationContext createApplicationContext() {
return new ClassPathXmlApplicationContext("classpath*:config/spring/testContext.xml");
}
}
#Component
public class SaveRoute extends SPRouteBuilder {
#Autowired
private SaveProcessor saveProcessor;
#Override
public void configure() throws Exception {
from("direct:SaveRoute")
.routeId("save")
.to("direct:ProcessSaveFlow")
.end();
from("direct:ProcessSaveFlow")
.process(saveProcessor)
.end();
}
}
public class SaveProcessor implements Processor {
#Autowired
SaveServiceClient saveServiceClient;
#Override
public void process(Exchange exchange) throws Exception {
//This line of code not able to mock
String response = saveServiceClient.invokeServiceWithName(exchange);
exchange.getIn().setBody(response);
}
}
How to resolve mocking of saveServiceClient.invokeServiceWithName? The debugger is always going inside this method. I tried using both mock objects and an injected mock. I can't make the method call directly.
You are creating a mock object, however you are not injecting it anywhere (normally you are doing it with #InjectMocks annotation - read about it).
I think there are several possibilities:
Provide a #MockBean object, which will be considered as a bean candidate in context.
There is a code example for mocking beans.
#RunWith ( CamelSpringRunner.class )
#SpringBootTest
public class RouteBuilderTest extends CamelSpringTestSupport {
#Autowired
private ApplicationContext applicationContext;
#MockBean
private ServiceClient serviceClient;
#Override
public void setUp() throws Exception {
MockitoAnnotations.initMocks( this );
super.setUp();
}
#Override
public void tearDown() {
}
#Test
public void test() {
when( serviceClient.doStuff() ).thenReturn( "mockedResponse" );
}
}
Mock SaveProcessor and inject it to Route class - you shouldn't take care of ServiceClient, because you are trying to test too much. Tests for SaveProcessor should be separated, tests for route don't need this logic.

Spring doesn't autowire fields when runner invokes '#Before' method

I have following test:
#RunWith(Parameterized.class)
#SpringBootTest
#ContextConfiguration(classes = MyConfig.class)
public class OrderPlacementCancelTest {
#Autowired
private TestSessionsHolderPerf sessionsHolder;
#ClassRule
public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
#Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
private CommonCredentialSetter commonCredentialSetter;
#Before
public void login() throws InterruptedException {
int attempts = 0;
while (!sessionsHolder.isClientLoggedIn() && attempts < 3) {
Thread.sleep(1000);
++attempts;
}
}
#Parameterized.Parameters()
public static Collection<Object[]> data() {
...
}
and following runner:
#Test
public void test() throws Exception {
Class[] cls = {OrderPlacementCancelTest.class};
Result result = JUnitCore.runClasses(new ParallelComputer(false, true), cls);
logger.info("Failure count={}", result.getFailureCount());
for (Failure failure : result.getFailures()) {
logger.error(failure.getTrace());
}
}
When I start test via runner I see that sometimes method login marked as #Before throws NullPointerException because sessionsHolder is null.
How can I avoid it?
It seems that #Parameterized does not mix well with junit rules. One option would be to replace the Rule by performing the logic in the constructor of the parameterized test class, or calling a setup method at the beginning of your test methods.
In either case you can use TestContextManager to populate your test class with the #AutoWired values like this:
private TestContextManager testContextManager;
#Before
public void login() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);

Categories