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);
Related
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.
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!
Method that needs to be tested - located in AnalyticsServiceImpl.java class
public void trackSplashState(MeasurementViewEnum measurementViewEnum) {
HashMap<String, Object> data = createCommonData(measurementViewEnum);
MeasureServiceImpl.StartStatus status = mMeasureService.getLaunchStatus();
switch (status) {
case INSTALL:
data.put(APP_EVENT_INSTALL, INSTALL);
break;
case LAUNCH:
data.put(APP_EVENT_LAUNCH, LAUNCH);
break;
case UPDATE:
data.put(APP_EVENT_UPDATE, UPDATE);
break;
}
trackState(measurementViewEnum, data);
}
Test class
#Config(constants = BuildConfig.class, sdk = TestConfig.SDK)
#RunWith(RobolectricTestRunner.class)
public class AnalyticsServiceImplTest {
#Module(includes = TestAppModule.class, injects = AnalyticsServiceImplTest.class, overrides = true)
static class TestModule {
}
#Inject
AnalyticsServiceImpl analyticsServiceImpl;
#Inject
MeasureServiceImpl measureService;
#Inject
Context mContext;
#Inject
LoginService mLoginService;
#Captor
ArgumentCaptor<HashMap<String, Object>> data;
#Captor
ArgumentCaptor<String[]> varargs;
private ArgumentCaptor<MeasurementViewEnum> enumArgumentCaptor;
#Before
public void setUp() throws Exception {
Services.initialize(new AnalyticsServiceImplTest.TestModule()).inject(this);
enumArgumentCaptor = ArgumentCaptor.forClass(MeasurementViewEnum.class);
}
#After
public void tearDown() throws Exception {
}
#Test
public void trackSplashState_shouldReturnInstall_whenLaunchStatusEqualsINSTALL() throws Exception {
analyticsServiceImpl = mock(AnalyticsServiceImpl.class);
MeasureServiceMock measureServiceMock = new MeasureServiceMock();
measureServiceMock.setStatus(MeasureServiceImpl.StartStatus.INSTALL);
analyticsServiceImpl.mMeasureService = measureServiceMock;
analyticsServiceImpl.trackSplashState(MeasurementViewEnum.SPLASH);
verify(analyticsServiceImpl, times(1)).trackState(enumArgumentCaptor.capture(), data.capture());
}
}
when I run this test case I got null pointer exception at the last line. I'm a bit new to unit testing. Can you please explain what is the mistake that I have done in this code?
1) You are mocking the SUT which simply wont work:
analyticsServiceImpl = mock(AnalyticsServiceImpl.class);
You will be verifying its trackState method so you need to Spy on it:
analyticsServiceImpl = spy(new AnalyticsServiceImpl());
2) You are capturing the inputs but you are not asserting them in any way. I guess you missed that:
verify(analyticsServiceImpl, times(1)).trackState(enumArgumentCaptor.capture(), data.capture());
Map<String, Object> dataCaptured = data.getValue();
MeasurementViewEnum enumCapture = enumArgumentCaptor.getValue();
// assert these values
UPDATE:
#Before
public void setUp() throws Exception {
MockitoAnnotation.initMocks(this);
}
QUESTION:
After putting my initialization into the actual #Parameters I no longer have a NullPointerException, is it possiuble that #Before isn't actually invoked before?!
Is there a solution so I don't have to put it into my Paramters?
Solution:
#RunWith(value = Parameterized.class)
public class XQTest4Test {
static XQueryTestHelper buildTest;
static HeaderBodyPayloadTestcase[] arrayHdrInbPayTestcases;
#Before
public void initialize() throws Exception {
buildTest = new XQueryTestHelper();
buildTest.initialization();
arrayHdrInbPayTestcases = buildTest.getHdrInbPayTestcases();
System.out.println(arrayHdrInbPayTestcases[0].a);
}
#Parameter
public HeaderBodyPayloadTestcase testcase;
#Parameters(name = "{index}: pew")
public static Iterable<? extends HeaderBodyPayloadTestcase> data() throws Exception {
buildTest = new XQueryTestHelper();
buildTest.initialization();
arrayHdrInbPayTestcases = buildTest.getHdrInbPayTestcases();
return Arrays.asList(arrayHdrInbPayTestcases);
}
#Test
public void someTest() throws Exception{
// System.out.println(xq.toString());
System.out.println(testcase.a);
if(testcase.c.contains("HDR")){
assertTrue(new XQueryTester(testcase.a,testcase.b).testHeader(testcase.c,testcase.d));
}
else if (testcase.c.contains("PAY")){
assertTrue(new XQueryTester(testcase.a,testcase.b).testBody(testcase.c,testcase.d));
}
else {
assertTrue(new XQueryTester(testcase.a,testcase.b).testInbound(testcase.c,testcase.d));
}
}
}
I think #Parameter annotation should help you. In this way you do not need a constructor with parameters.
#RunWith(Parameterized.class)
public class XQTest4Test {
static XQueryTestHelper buildTest;
static HeaderBodyPayloadTestcase[] arrayHdrInbPayTestcases;
#Parameter
public HeaderBodyPayloadTestcase testcase;
#Parameters(name = "{index}: pew")
public static Iterable<Object[]> data() {
return Arrays.asList(new HeaderBodyPayloadTestcase[][]{arrayHdrInbPayTestcases});
}
// ...
}
And ensure that access modifier of field marked as #Parameter is public.
I would recommend you to do all the initialization in #Before or #BeforeClass methods. Depends on you logic.
This feature is well-documented on JUnit4 wiki
The following code returns Expectation failure of verification:
What's up with the code?
can someone help me what am I missing there?
public class DAOImplTest {
private DAOImpl dao;
private JdbcTemplate mockJdbcTemplate;
#Before
public void before() {
dao = new DAOImpl();
mockJdbcTemplate = createMock(JdbcTemplate.class);
dao.setJdbcTempate(mockJdbcTemplate);
}
#After
public void after() {
dao = null;
}
#SuppressWarnings("unchecked")
#Test
public void methReturnsWhenOrgIdsAndGuidFound(){
final String expectedOrgIds = "d514d112566e";
final String expectedGUID = "one";
expect(mockJdbcTemplate.queryForObject(eq(SSOSASguidDAOImpl.GET_GUID_FOR_ORG_IDS),
(RowMapper<String>) anyObject(), eq(expectedGUID), eq(expectedOrgIds))).andReturn(expectedOrgIds);
replay(mockJdbcTemplate);
// verify(mockJdbcTemplate, expectedOrgIds);
verify(mockJdbcTemplate);
assertNotNull(expectedOrgIds);
assertEquals("d514d112566e", expectedOrgIds);
}
}
Wondering why it is throwing an error on verify?
The call to replay should be followed by a call the the expected methods, in your case, you should call the mockJdbcTemplate.queryForObject(); method with appropriate parameters; before calling the verfiy method.