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

Hazelcast, HazelcastSerializationException when putting data to map
Trying to run multiple python scripts in Java
The attribute nativeQuery is undefined for the annotation type Query
How to reduce the waiting time of Android SpeechRecognizer API?
Extract Text From EditText and Print in TextView
FFMpeg not muxing audio and video
Java desktop application excel upload with Apache POI
Lucene suggestion (behavior of SUGGEST_MORE_POPULAR flag)
Android - MPAndroidChart - LineChart not showing line
BigDecimal in android api 16
How can i pas a hasmap in java web service whose key is string and value again a hasmap from IBM BPM?
Java Priority Queue Comparator FIFO order [duplicate]
Alternative to #StringDef in non Android modules
Java: How to terminate the process created with ProcessBuilder(“startx”, “firefox”)
IllegalStateException without any root cause
Websocket Binary message from Tomcat 9 to client splitted to 2 or more tcp packets

Categories

HOME
java
testing
wso2-am
heroku
drivers
angular-material
jira
ckeditor
datastax-java-driver
uber-api
slick-slider
maude-system
windows-10-universal
node-pdfkit
here-api
nano-server
nstableview
moonmail
dtrace
event-handling
clojurescript
libtiff
pc
footer
google-static-maps
facebook-instant-articles
kudan
lcd
cas
bootstrap-duallistbox
brunch
facebook-apps
bpel
gsoap
frame
junit5
iframe-resizer
yadcf
phonegap
siesta-swift
column-family
mpmediaquery
http-digest
git-merge
code-search-engine
webdriver-manager
lumberjack
graphenedb
businessworks
long-polling
parentheses
directory-structure
jspdf-autotable
deadbolt-2
autorest
holder.js
angstrom-linux
fadeout
ford-fulkerson
jqgrid-formatter
wyam
createprocessasuser
mmc
jsapi
website-monitoring
qcodo
websocket4net
starcluster
fluentautomation
expected-exception
app42
centos5
html5-notifications
terminal-services
django-nonrel
ocunit
referrer
browser-detection
nsnetservice
multipage
javaspaces
tridion-worldserver
viewswitcher
netbeans-6.9
buildr
netbeans-7.1
disclosure
cxxtest
digest-authentication
paster
nhibernate.search
nerddinner
w3wp
mdac
django-notification

Resources

Encrypt Message