mockito.veify() is giving wrong invocation count - java

I am trying mockito.verify() feature, the method invocation is only once but verify is showing invocation 3 times. The unit test has only one test, to ensure no other way this test get affected.
Mockito.verify(utilClass, Mockito.times(1)).hello(); /// but invocation is 3 times, is the error
I have tried using log, which is showing invocation is once. Added deliberate calling method utilClass.hello() more than once, then showing correct no of invocations.but in the given code where it is called once, is showing as called 3 times.
Class to be tested:
#Component
public class UtilClass {
private static final Logger logger = LoggerFactory.getLogger(UtilClass.class);
public String hello() {
logger.info("hello method invoked");
return "Hello World,"+ hi();
}
private String hi() {
logger.info("hi method invoked");
return "Hi All";
}
}
#Component
public class ClassWithDependency {
#Autowired
private UtilClass utilClass;
public String welcome() {
String msg = utilClass.hello();
return msg;
}
}
Test case
#InjectMocks
private ClassWithDependency classWithDependency;
#Mock
private UtilClass utilClass;
#Before
public void init() throws Exception {
PowerMockito.when(utilClass,"hi").thenReturn("Hi Java");
PowerMockito.when(utilClass.hello()).thenCallRealMethod();
}
#Test
public void testMock() throws Exception {
final String msg = classWithDependency.welcome();
final String msgExpected = "Hello World,Hi Java";
logger.info("welcome method called:{}",msg);
PowerMockito.verifyPrivate(utilClass, Mockito.times(1)).invoke("hi");
Mockito.verify(utilClass, Mockito.times(1)).hello();
Assert.assertTrue(msg.equals(msgExpected));
}
I am expecting the mockito.verify to be successful, but getting error
org.mockito.exceptions.verification.TooManyActualInvocations:
utilClass.hello();
Wanted 1 time:
-> at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
But was 3 times:
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
-> at com.sd.demo.powermock.injectmock.ClassWithDependency.welcome(ClassWithDependency.java:13)
at com.sd.demo.powermock.test.injectmock.InjectMockTest.testMock(InjectMockTest.java:54)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
.............

Finally make the test working, the solution is 'SPY'.. Spy on util class, so that not to tell which method to make real call. I am not sure how to inject spy, so used a setter..
#InjectMocks
private ClassWithDependency classWithDependency;
private UtilClass mockUtil;
#Before
public void init() throws Exception {
UtilClass utilClass = new UtilClass();
mockUtil = PowerMockito.spy(utilClass);
classWithDependency.setUtilClass(mockUtil);
}
#Test
public void testMock() throws Exception {
PowerMockito.when(mockUtil,"hi").thenReturn("Hi Java");
final String msg = classWithDependency.welcome();
final String msgExpected = "Hello World,Hi Java";
logger.info("welcome method called:{}",msg);
PowerMockito.verifyPrivate(mockUtil, Mockito.times(1)).invoke("hi");
Mockito.verify(mockUtil, Mockito.times(1)).hello();
Assert.assertTrue(msg.equals(msgExpected));
}

Related

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.

Mock method return type in java

Below is main code consist of one util class and service class using it
#PropertySource("classpath:atlas-application.properties")
public class ApacheAtlasUtils {
#Value("${atlas.rest.address}")
private String atlasURL;
#Value("${atlas.rest.user}")
private String atlasUsername;
#Value("${atlas.rest.password}")
private String atlasPassword;
private AtlasClientV2 client;
public AtlasClientV2 createClient() {
if (client == null) {
return new AtlasClientV2(new String[] {atlasURL}, new String[] {atlasUsername, atlasPassword});
} else {
return client;
}
}
}
Service Class is below :-
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
I am writing unit test for service method and I am getting exception for createClient method asking for values for url, username and password which should not happen as this should be mocked but the mocking is giving me below error
java.lang.IllegalArgumentException: Base URL cannot be null or empty.
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:141)
at org.apache.atlas.AtlasServerEnsemble.<init>(AtlasServerEnsemble.java:35)
at org.apache.atlas.AtlasBaseClient.determineActiveServiceURL(AtlasBaseClient.java:318)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:460)
at org.apache.atlas.AtlasBaseClient.initializeState(AtlasBaseClient.java:448)
at org.apache.atlas.AtlasBaseClient.<init>(AtlasBaseClient.java:132)
at org.apache.atlas.AtlasClientV2.<init>(AtlasClientV2.java:82)
at com.jlr.stratus.commons.utils.ApacheAtlasUtils.createClient(ApacheAtlasUtils.java:40)
at com.jlr.stratus.rest.service.impl.FileSearchService.findFilesWithPages(FileSearchService.java:49)
The Test code is as follows:-
private FileSearchService fileSearchService;
#Spy
private ApacheAtlasUtils apacheAtlasUtils;
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
fileSearchService = new FileSearchService();
}
#Test
public void findFilesWithPages_searchAll() throws AtlasServiceException {
Mockito.doReturn(client).when(apacheAtlasUtils).createClient();
service.search(queryParent,pageable);
}
Your idea with spying is adequate (you can even go for mocking if you do not actually need any true implementation of that class).
The problem lies in the implementation:
// Some code
client = new ApacheAtlasUtils().createClient();
//some code
}
Instead of having the ApacheAtlasUtils as an instance variable (or a supplier method) you create the instance on the fly.
Mockito is not smart enough to catch that operation and replace the real object with you spy.
With the supplier method you can set up your test as follows:
#Spy
private FileSearchService fileSearchService = new FileSearchService();
#Spy
private ApacheAtlasUtils apacheAtlasUtils = new ApacheAtlasUtils();
#Mock
private AtlasClientV2 client;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
doReturn(apacheAtlasUtils).when(fileSearchService).getApacheUtils();
}
in your SUT:
#Override
public Page<SearchResultDto> findFilesWithPages(QueryParent queryParent, Pageable pageable)
throws AtlasServiceException {
// Some code
client = getApacheUtils().createClient();
//some code
}
ApacheAtlasUtils getApacheUtils(){
return new ApacheAtlasUtils();
}

how do i mock method, calling one method from another method?

I'm New in Mocking.
I've a service I'm trying to call is let say name A, I need to test someMethod.
#Service
public class A {
private Logger logger = LoggerFactory.getLogger(getClass());
private final CoreXReader coreXReader;
#Autowired
B b;
#Autowired
C c;
#Async
public void someMethod(Config config) throws Exception {
pushConfig(config);
}
private void pushConfig(Config config) throws Exception {
String url = config.getBaseurl() + config.getId();
ABCRestClient restClient = new ABCRestClient(url);
String jobJson = restClient.callRestMethod(HttpMethod.GET, "");
}
}
sample of ABCRestClient
public class ABCRestClient {
private Logger logger = LoggerFactory.getLogger(getClass());
private String url;
public ABCRestClient(String url) {
this.url = url;
}
public String callRestMethod(HttpMethod method, String payload) throws Exception {
someresponse="example response";
return someresponse;
}
}
I'm trying to test by creating mockSpy but it still Calling its 'callRestMethod'
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClient = new ABCRestClient(config.getBaseurl() + config.getId() );
ABCRestClient apiClientSpy=Mockito.spy(apiClient);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}
i'm not sure what I'm doing wrong here why its calling the actual callRestMethod as i already create a spy .
I tried using this too Mockito.doReturn(getCallResponse()).when(apiClientSpy.callRestMethod(HttpMethod.GET, ""))
Also, is there any difference in these two statement if I use it Mockito.doReturn() or directly doReturn()? In my case both seems behaving same.
Before I tried with this as well when().thenReturn(); but I read somewhere that use when().thenReturn() when you actually want to make call. Please correct if my understanding is wrong.
You can try mock instead of spy:
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment=
SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClientSpy=Mockito.mock(ABCRestClient.class);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}

Unit test singleton class method in android using PowerMock

I need to do unit testing of methods of Singleton class which internally uses RxJava Singles, and used PowerMock test framework to mock static class and methods. I tried various method to mock Schedulers.io() and AndroidSchedulers.mainThread() methods but it's not working. I'm getting java.lang.NullPointerException error at line .subscribeOn(Schedulers.io()) inside UserApi.verifyUserData() method.
Singleton Class UserApi (Class under Test)
final public class UserApi {
private CompositeDisposable compositeDisposable;
private String userID;
//private final SchedulerProvider schedulerProvider;
private UserApi(String userId) {
super();
this.userID = userId;
//this.schedulerProvider = schedulerProvider;
}
public static UserApi getInstance() {
return SingletonHolder.sINSTANCE;
}
private static final class SingletonHolder {
private static final UserApi sINSTANCE;
static {
String uuid = UUID.randomUUID().toString();
sINSTANCE = new UserApi(uuid);
}
}
// Rest Api call
public void verifyUserData(byte[] doc, byte[] img) {
this.compositeDisposable = new CompositeDisposable();
String docStr = Base64.encodeToString(doc, Base64.NO_WRAP);
String imgStr = Base64.encodeToString(img, Base64.NO_WRAP);
final Disposable apiDisposable = IdvManager.getInstance().getUserManager().verifyUserData(docStr, imgStr)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<JsonObject>() {
#Override
public void accept(JsonObject verifyResponse) throws Exception {
pollResult();
}
}, new Consumer<Throwable>() {
#Override
public void accept(Throwable error) throws Exception {
// handle error code...
}
});
this.compositeDisposable.add(apiDisposable);
}
private void pollResult() {
// code here...
}
}
UserManager Class and Interface
public interface UserManager {
Single<JsonObject> verifyUserData(String docStr, String imgStr);
}
final class UserManagerImpl implements UserManager {
private final UserService userService;
UserManagerImpl(final Retrofit retrofit) {
super();
this.userService = retrofit.create(UserService.class);
}
#Override
public Single<JsonObject> verifyUserData(String docStr, String imgStr) {
// Code here...
}
}
Unit Test
#RunWith(PowerMockRunner.class)
#PrepareForTest({IdvManager.class, Base64.class, Schedulers.class, AndroidSchedulers.class, UserApi.class})
public class UserApiTest {
#Mock
public UserManager userManager;
#Mock
private Handler handler;
private IdvManager idvManager;
private Schedulers schedulers;
private UserApi spyUserApi;
private TestScheduler testScheduler;
private String userID;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
testScheduler = new TestScheduler();
handler = new Handler();
PowerMockito.suppress(constructor(IdvManager.class));
// mock static
PowerMockito.mockStatic(IdvManager.class);
PowerMockito.mockStatic(Schedulers.class);
PowerMockito.mockStatic(AndroidSchedulers.class);
PowerMockito.mockStatic(Base64.class);
// Create mock for class
idvManager = PowerMockito.mock(IdvManager.class);
schedulers = PowerMockito.mock(Schedulers.class);
PowerMockito.when(IdvManager.getInstance()).thenReturn(IdvManager);
when(idvManager.getUserManager()).thenReturn(userManager);
spyUserApi = PowerMockito.spy(UserApi.getInstance());
// TestSchedulerProvider testSchedulerProvider = new TestSchedulerProvider(testScheduler);
when(Base64.encodeToString((byte[]) any(), anyInt())).thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return java.util.Base64.getEncoder().encodeToString((byte[]) invocation.getArguments()[0]);
}
});
when(schedulers.io()).thenReturn(testScheduler);
when(AndroidSchedulers.mainThread()).thenReturn(testScheduler);
userID = UUID.randomUUID().toString();
}
#After
public void clearMocks() {
//Mockito.framework().clearInlineMocks();
}
#Test
public void verifyUserData_callsPollResult_returnsResponse() {
// Input
String docStr = "iVBORw0KGgoAAAANSUhEUgAAAJ4AAACeCAYAAADDhbN7AA.....";
// Output
JsonObject verifyResponse = new JsonObject();
verifyResponse.addProperty("status", "Response created");
doReturn(Single.just(verifyResponse)).when(userManager).verifyUserData(docStr, docStr);
// spy method call
spyUserApi.verifyUserData(docFrontArr, docFrontArr);
testScheduler.triggerActions();
// assert
verify(userManager).verifyUserData(docStr, docStr);
}
}
Error
java.lang.NullPointerException
at com.rahul.manager.UserApi.verifyUserData(UserApi.java:60)
at com.rahul.manager.UserApiTest.verifyUserData_callsPollResult_returnsResponse(UserApiTest.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
I'm not sure whether i can test methods of Singleton class by spying on real instance of Singleton class using PowerMock.
Testing your code is complex because it's not testable and it's not extensible. It contains hardcoded dependencies everywhere (e.g. user id, handler, several singletons).
If you decide to use another id generation approach or another handler, you won't be able to do this without rewriting whole class.
Instead of hardcoding dependencies, ask for them in constructor (for mandatory dependencies) or setters (for optional ones).
This will make your code extensible and testable. After you do this, you will see your class contains several responsibilities, after moving them into separate classes, you will get much better picture :-)
For example:
public UserApi(String userId, Handler handle) {
this.userId = userId;
this.handler = handler;
}
Schedulers.io() is a static method, so you need to use mockStatic (which you did) and define the related mock accordingly.
I rearranged your setup method a bit, to improve the readability and fixed the mistake. You do not need an instance of Schedulers (The variable you named schedulers).
Probably a simple typo you made, as you did the right thing for Base64 and AndroidSchedulers.
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
testScheduler = new TestScheduler();
handler = new Handler();
// mock for instance of `IdvManager`
PowerMockito.suppress(constructor(IdvManager.class));
idvManager = PowerMockito.mock(IdvManager.class);
when(idvManager.getUserManager()).thenReturn(userManager);
// mock for `IdvManager` class
PowerMockito.mockStatic(IdvManager.class);
PowerMockito.when(IdvManager.getInstance()).thenReturn(idvManager);
// mock for `Schedulers` class
PowerMockito.mockStatic(Schedulers.class);
when(Schedulers.io()).thenReturn(testScheduler);
// spy for instance of `UserApi`
spyUserApi = PowerMockito.spy(UserApi.getInstance());
// mock for `Base64` class
PowerMockito.mockStatic(Base64.class);
when(Base64.encodeToString((byte[]) any(), anyInt())).thenAnswer(new Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return java.util.Base64.getEncoder().encodeToString((byte[]) invocation.getArguments()[0]);
}
});
// mock for `AndroidSchedulers` class
PowerMockito.mockStatic(AndroidSchedulers.class);
when(AndroidSchedulers.mainThread()).thenReturn(testScheduler);
userID = UUID.randomUUID().toString();
}
However the NPE is missing the part that actually indicates its failing from this, consider adding it if that does not solve your problem.

java.lang.AssertionError: Expectation failure on Verify: jUnit4 TestCase

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.

Categories