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

Functions return leaf of tree
How to get the sonar administration permission,when I use http.client.fluent.Request
What is the best data strcture to choose and implementation to build for this kind data in Java? [closed]
Need help creating a “help” command that a user can type at any point and see keywords or get help if they are stuck
linkedlist add and remove not working as expected, Java
Trouble passing objects for computation between client and server in Java
How to make div scrollable, please go through once before marking as a duplicate
Why does Java Garbage Collection perform in batch? [closed]
Android studio pass ListView to another activity
Java HDFS 2.6.1 async write/flush
How to chain two Completable in RxJava2
Android Studio (or just java) Get Audio Spectrum (DB/HZ) of .mp3 file
Why automatic garbage collection eliminates ABA proble?
A generic and robust tool to automate validation of all kinds of xml having duplicate values
Reading and writing objects in a file in java
Remote debugging java app

Categories

HOME
yii2
netbeans
azure-data-factory
layout
office365api
youtube-dl
getelementsbytagname
analysis
cmd
jpeg
callback
convolution
azure-media-services
podio
directx
volttron
postgres-xl
decomposition
tostring
facebook-page
pythonanywhere
reverse-proxy
crosstab
fish
pingfederate
dbclient
libuv
bosh
siesta-swift
google-sites-2016
fog
copying
form-data
sequential
fusionpbx
espeak
withings
xenforo
dism
unoconv
turbogears
bootstrap-dialog
outlook-api
import-from-excel
jedis
errordocument
mplayer
knockout-components
dtexec
akka-cluster
crosswalk-runtime
abcpdf9
wdf
bonobo
home-directory
azure-virtual-network
mikroc
py2app
markojs
dataview
rhino-servicebus
asp.net5
two-factor-authentication
srand
spim
wireshark-dissector
cisco-ios
sonarqube5.1.2
proj4js
apache-commons-net
bigbluebutton
formatjs
tween
camanjs
java.util.concurrent
phpthumb
marmalade
picturefill
cos
selected
typoscript2
trusted
automount
transactionscope
nsdatecomponents
yui-datatable
remember-me
lpeg
createwindow
dentrix
mirah
adrotator
swing-app-framework
eqatec
gacutil
zune
grid-system

Resources

Database Users
RDBMS discuss
Database Dev&Adm
javascript
java
csharp
php
android
javascript
java
csharp
php
python
android
jquery
ruby
ios
html
Mobile App
Mobile App
Mobile App