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

Using FileProvider with getExternalMediaDirs() - “failed to find configured root Android/media”
Why this code is showing terminated due to timeout on hackerrank
Loading resultset from JDBC into two-dimensional table
java.lang.ClassNotFoundException WindowManager
How to send post http request in java for wit.ai audio
log4j dont write in file
Why am I getting this error array index out of bounds
Get data from multiple tables based on entities in spring jpa
How to get last object from a JSONArray
Weblogic 12c - EJB 3.1 MDB How to apply filtering on JSON Message
Controller method without PathVariable removes all entitites
Detect top of reversed RecyclerView
Error while loading java.util.concurrent.TimeoutException android
Handling duplicate regex group name in Java (C# translation)
spring 4 #validation annotation with bindingresult is not working
Connect to a remote Web socket channel

Categories

HOME
xamarin
yii2
coq
single-sign-on
relayjs
setup-deployment
infragistics
frameworks
cakephp-2.5
cross-browser
yum
pheatmap
elasticsearch-hadoop
session-variables
adobe-analytics
fancybox-3
spring-xd
google-apps-marketplace
jplayer
gz
commonmark
msp430
hapi
seaborn
lldb
xlsxwriter
riot.js
web-sql
pass-by-reference
icloud-api
chromebook
brunch
web-api-testing
tasklet
file-rename
unboundid
media-queries
google-cloud-endpoints-v2
http-status-code-503
kendo-ui-grid
lxd
phpfreechat
repo
xmlreader
android-nestedscrollview
hexo
catalog
bytecode-manipulation
objectlistview
vapor
reportbuilder
ansible-playbook
sas-visual-analytics
sql-server-agent
g-code
spring-security-kerberos
no-www
businessworks
pango
dotnetzip
statsd
recursive-datastructures
r-forge
dynamics-sl
or-tools
background-service
android-textview
home-directory
file-writing
intrusion-detection
impresspages
storekit
persist
prettytensor
superstack
yaws
bluemix-app-scan
natvis
vhd
spim
content-length
system.reflection
sorl-thumbnail
operator-precedence
jscript.net
phalanger
castle
p4java
jquery-layout
valueconverter
fmod
multiprocessor
http-unit
cassini-dev
sublist
funscript
tridion-worldserver
punbb
adk
self-extracting
pyinotify
google-friend-connect
dmx512
gamma
audio-capture
ti-dsp
xetex

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