I have been trying to mock a method of a class. The method is reading a configuration from file. The file consists of a URI of a service. Method is reading URI from file and creating a WebTarget object. I have been running a testng mockito test case and I am trying to return a string from a mock method when this method is called. Problem is whenever this method is called then actual method is called and it tries to read the file. However, (Correct me if I am wrong) it should not call the actual method and returns the mocked response. Somehow, it is not working. Below is the code for the test
@Mock
private ExternalApiConfig externalApiConfig = null;
public CisAccountServiceImpl cisAccoutService;
@BeforeMethod
public void init() {
MockitoAnnotations.initMocks(this);
externalApiConfig = Mockito.mock(CisApiConfig.class);
}
private void testUpdateServiceAddressCoordinates(Account account) throws IOException {
Mockito.when(externalApiConfig.getExternalUrl()).thenReturn("http://localhost:8080/serviceURI/");
cisAccoutService = new CisAccountServiceImpl();
assertThat(account, is(notNullValue()));
List<PremiseExtension> premiseExtensions = account.getPremise().getPremiseExtension();
assertThat(premiseExtensions.size(), is(30));
String geoXSettingName = "value2";
String geoYSettingName = "value3";
Double lat = 24.0;
Double lng = -98.0;
boolean updated = cisAccoutService.updateAccountGeoLocation(accountId,
lat, lng, geoXSettingName, geoYSettingName);
assertThat(true, is(updated));
Account updatedAccount = getAccountById();
assertThat(Double.parseDouble(updatedAccount.getPremise().getPremiseExtension().get(2).getValue()), is(equals(lat)));
assertThat(Double.parseDouble(updatedAccount.getPremise().getPremiseExtension().get(3).getValue()), is(equals(lng)));
//rollback the change
updatedAccount.getPremise().setPremiseExtension(premiseExtensions);
updateAccountWithValues(updatedAccount);
}
The method I want to mock is externalApiConfig.getExternalUrl() in following code
public class CisRestBaseService {
protected WebTarget rootWebTarget;
protected ExternalApiConfig externalApiConfig;
public CisRestBaseService() {
JacksonJsonProvider jacksonJsonProvider = new JacksonJaxbJsonProvider()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
Client jaxRsClient = ClientBuilder.newClient().register(jacksonJsonProvider);
this.externalApiConfig = new CisApiConfig();
this.rootWebTarget = jaxRsClient.target(externalApiConfig.getExternalUrl());
}
}
Any help would be much appreciated.
the problem is that you are not passing the mocked externalApiConfig
to the tested class CisRestBaseService
. To fix this, you can, for example, define it it as a constructor argument (you can keep the current constructor as well if needed).
public CisRestBaseService(CisApiConfig config) {
JacksonJsonProvider jacksonJsonProvider = new JacksonJaxbJsonProvider()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
Client jaxRsClient = ClientBuilder.newClient().register(jacksonJsonProvider);
this.externalApiConfig = config;
this.rootWebTarget = jaxRsClient.target(externalApiConfig.getExternalUrl());
}
public CisRestBaseService() {
this(new CisApiConfig());
}
Not, from the test, you can instantiate the service like this:
Mockito.when(externalApiConfig.getExternalUrl()).thenReturn("http://localhost:8080/serviceURI/");
cisAccoutService = new CisAccountServiceImpl(externalApiConfig);
As a result, your service under test will use the mock instead of creating a real config object.This technique is called "dependency injection", you can read more about it here: https://www.digitalocean.com/community/tutorials/java-dependency-injection-design-pattern-example-tutorial