java


What is the best way to mock object instantiated inside method under test?


I have the following code and I look for the best way to test it:
public class ClientFactory {
private ConfigurationLoader loader;
public ClientFactory(ConfigurationLoader loader) {
this.loader = loader;
}
public IRest create(String something) {
Configuration config = loader.load(something);
if (magic()) {
return new ClientType1(config);
}
return new ClientType2(config);
}
}
public class ClientType1 implements IRest{
private Configuration config;
public ClientType1(Configuration config) {
this.config = config;
}
public Something doGetRequest(Long id) {
WebClient client = getHttpClient();
return client.get();
}
private WebClient getHttpClient() {
WebClient client = new WebClient();
client.setSchema(config.getSchema());
client.setHostname(config.getHostname());
client.setPort(config.getPort());
// and so on ....
return client;
}
}
I would like to test the interaction/behaviour between ConfigurationLoader and ClientType1.getHttpClient methods. From one side I think it is good idea, testing interaction between objects, from the other side, hmmm I test setters and getters - boring, no business logig is involved here. Which one is more true?
Mock of configuration object can be easily transferred into ClientType1 when it is instantiated, mocking the 'new WebClient()' seems to be the problem. I thought about:
public class ClientType1 implements IRest{
private Configuration config;
private WebClient client; // this will be replaced by mock
public ClientType1(Configuration config) {
this.config = config;
webClient = new WebClient();
}
.....
private Client getHttpClient() {
client.setSchema(config.getSchema());
....
return client;
}
}
and use PowerMock to replace private WebClient client by mock, but I am not sure it is java way. Any guidelines/suggestions?
As you have found, the new keyword makes unit testing difficult. I suggest avoiding it. I think your problem here is more of a design problem. Objects should not configure themselves. When you design an object, think about what its true dependencies are. IMO the true dependency of the ClientType1 is a WebClient or a pool of WebClient not a Configuration. IMO the true dependency of ClientFactory is a Configuration not a String.
I would redesign like so:
interface ClientFactory {
IRest create(Configuration config);
}
public class DefaultClientFactory implements ClientFactory {
private final ClientFactory magicClientFactory;
private final ClientFactory otherClientFactory;
public DefaultClientFactory(ClientFactory magicClientFactory, ClientFactory otherClientFactory) {
this.magicClientFactory = magicClientFactory;
this.otherClientFactory = otherClientFactory;
}
public IRest create(Configuration config) {
if (magic()) {
return magicClientFactory.create(config);
} else {
return otherClientFactory.create(config);
}
}
}
interface WebClientFactory {
WebClient create(Configuration config);
}
public class DefaultWebClientFactory implements WebClientFactory {
public WebClient create(Configuration config) {
WebClient client = new WebClient();
client.setSchema(config.getSchema());
client.setHostname(config.getHostname());
client.setPort(config.getPort());
return client;
}
}
public class ClientType1Factory implements ClientFactory {
private final WebClientFactory webClientFactory;
public ClientType1Factory(WebClientFactory webClientFactory) {
this.webClientFactory = webClientFactory;
}
public IRest create(Configuration config) {
return new ClientType1(webClientFactory.create(config));
}
}
public class ClientType1 implements IRest{
private final WebClient webClient;
public ClientType1(WebClient webClient) {
this.webClient = webClient;
}
public Something doGetRequest(Long id) {
return webClient.get();
}
}
Using this design you can successfully unit test each and every class defined without resorting to advanced features of PowerMock. You can unit test ClientType1 by passing in a mock WebClient. You can also test your factories by passing in different configurations and checking if the created object is what you expect. Further the code is less coupled, more flexible, and each class has a single responsibility.

Related Links

Hive-Java App connection on Cloudera 5.8.0 QuickStartVM
Webhook notifications for Google drive changes not received
JAX-WS didn't get response on Websphere 8.5
Java: JDOM2 write ascii character in xml
How to know which hibernate jar tomcat is using? [duplicate]
How to access JNA in Android Studio
Getting number format excpetion
How i can calculate sum with filter and show result in table
Is there a way to get all errors from executeBatch?
Many calls to the server
Is a usage of array of references to a generic type better than using an array of raw types? [duplicate]
Stream of cartesian product of other streams, each element as a List?
SQL in Java Select From Where
How can programs written in Java not require the JRE?
How to add a character to both sides of a word of a string in java?
LayoutInflator in ArrayAdapter's getView() gives me UnsupportedOperationException: addView(View, LayoutParams) is not supported in AdapterView

Categories

HOME
openlayers
drivers
mfc
path-finding
relative-path
filtering
amazon-ecs
graphql
in-app-purchase
adfs
slick-slider
primary-key
communication
fallback
hapi
percona
pc
kryo
orleans
cloudhub
functional-testing
emgucv
sqlcipher
assistant
jspm
microsoft-chart-controls
ecto
yadcf
galsim
data-manipulation
pdb
column-family
code-contracts
mozilla
swift3.0.2
sharefile
hue
streamreader
leading-zero
slick-3.0
btrace
user-accounts
osx-mavericks
revapi
git-diff
libusb-win32
font-size
webdriverjs
query-performance
watchconnectivity
rotativa
savon
database-optimization
dstu2-fhir
paypal-express
gridview-sorting
persist
fadeout
php-parse-error
python-3.2
tmuxinator
purge
jqgrid-formatter
ibaction
mmc
bridge.net
c++03
system.reflection
formatjs
dia
sorl-thumbnail
website-monitoring
gui-test-framework
nsbutton
wordpress-theme-customize
neolane
jubula
rebol3
comexception
undefined-reference
comaddin
sharp-repository
lcs
selected
sublist
isnullorempty
tridion-worldserver
objective-c-2.0
pendrive
php-parser
spyware
blackberry-playbook
coercion
xmlspy
django-tagging
sql-server-profiler
modelstate
routedevent
ncqrs
webkit.net
zend-tool
nintendo-ds
ctp4
pascal-fc
putchar
dbisam

Resources

Mobile Apps Dev
Database Users
javascript
java
csharp
php
android
MS Developer
developer works
python
ios
c
html
jquery
RDBMS discuss
Cloud Virtualization
Database Dev&Adm
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App