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

Anagram Algorithm Clarification
Create nGramms out of text with blacklist
Base Level User Input that writes code into the program?
Undestanding how to use JPA to abstract the ORM
AES vs PBEWithSHA256And256BitAES
How can I ensure that a method returns a value?
Move circle around jpanel using keylistener
Java Timer Code
UTF-16BE and UTF-16 issue in java
can we inherit base class constructor in java [duplicate]
Convert JSONObject into string and long return null
getOutputStream in HttpServletResponseWrapper getting called multiple times
Create Custom View and Add to XML
“Hello World” program has generated an exception
View Flipper that uses Only One ImageView
java.io.FileNotFoundException when using Jsoup

Categories

HOME
openlayers
variables
clips
cookies
urbancode
comparison
dot
octobercms
webstorm
alfresco
amortized-analysis
rubygems
packages
survey
adfs
metatrader4
u-sql
etl
fortumo
opentracing
highlight.js
samoa
dbext
swingx
tokenize
mps
zurb-foundation-6
cultureinfo
android-widget
qhull
apache-commons-io
django-storage
google-cloud-nl
xquery-3.0
uisplitview
protovis
openoffice.org
http-referer
mixture-model
theano.scan
uft-api
android-fingerprint-api
trim
sas-visual-analytics
eclipse-scout
.net-4.6.2
apple-news
jquery-validate
typescript1.8
pebble-watch
csound
magma
nsarray
flutterwave
synchronous
google-cdn
setuptools
elements
file-writing
underscore.js-templating
ctest
flash-cs5
netmq
marching-cubes
jqgrid-formatter
generic-programming
npapi
codeigniter-routing
titanium-modules
starcluster
fluentautomation
doskey
imdbpy
geos
odata4j
ftps
easy-install
flashvars
simba
quickdialog
dice
jspinclude
getmessage
online-compilation
postgresql-performance
gnu-prolog
blackberry-playbook
f#-powerpack
winbugs14
imac
floating
visitor-statistic
fluent-interface
gamma
virtual-functions
eqatec
privilege
mediarss

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile