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

Removing duplicated nodes from sorted linked list. Why is my output wrong?
Collections Sort to sort both ArrayLists the same
How to read this XML file in Java? [duplicate]
how to read bullets from RTF file
Jquery dataTable warning while displaying JSON objects from servlet
JavaFX - Platform.runLater is not being executed on mac
Why does org.springframework.validation.Validator NOT implement validate() with groups
how to call .net dll in JMeter
scala.collection.Seq doesn't work on Java
Is it possible to perform an action event over a line?
CAS login-webflow modified adding view during ticket check
java program to display whether strings are palindrome and also show if not which characters don't match
Soap response header element parsing through JAXB
Client-server data synchronization data structure in android?
Sharing memory between two different applications developed in different languages
TypedQuery cannot proceed with boolean in where block

Categories

HOME
hook
amazon-ec2
platform-builder
routes
jsrender
youtube-api-v3
jpeg
icloud
flyway4
session-variables
numeral.js
qt-creator
nstableview
task
ibm-odm
dynamics-crm-online
workload-scheduler
ab-testing
openedx
emulator
jtextfield
scriptcs
css-animations
tapestry
kudan
dxf
nhapi
web-api-testing
log4js-node
objectanimator
bluestacks
ecto
key-value-observing
semantic-versioning
mapdb
fusionpbx
overlap
lto
mixture-model
android-browser
elasticsearch-plugin
trim
mapzen
gzipstream
http-live-streaming
nxlog
galleria
long-polling
azure-application-gateway
filepicker
dds
promela
aurelia-validation
knpmenubundle
sqlbulkcopy
cudafy.net
jspdf-autotable
migradoc
google-feed-api
rotativa
intrusion-detection
phishing
nsfilemanager
mongocsharpdriver
rhino-servicebus
revolution-r
cloudbees
freelancer.com-api
prerequisites
iis-arr
jqgrid-formatter
varargs
ionic
service-accounts
method-parameters
generic-programming
web-controls
streambase
truevault
c++03
directoryservices
javax.mail
applescript-objc
device-manager
pyhdf
multiprocessor
html4
dataadapter
mqx
eventlistener
mhtml
mt
pysimplesoap
regsvr32
assembly-loading
heartbeat
rfc1123
appender
recent-documents
oncheckedchanged
android-sdk-2.1
mongomapper
vc90
perfect-hash
zend-tool
avatar
sustainable-pace
project-hosting
nerddinner
msdev
windows-live-messenger

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile