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

Java EE authentication: how to capture login event?
Add qualified class to Java comment instead of importing the class
Got 404 error on tomcat 7.0.47 websocket
Maven Java Project Only Working Once
drag object using mouse Listener
How to remove 2 or more spaces that are next to each other from a char array
Java int array incremented with start and end points
Another Comparison method that violates its contract [duplicate]
FTP proxy design: how to shutdown data channel properly at client side
NullPointerException at mapFragment.getMapAsync
Cannot create ActiveMQ queue or send a message using java
Type of constant expressions in Java [duplicate]
Hazelcast MapStore Load with TTL
Dynamic TableView in Javafx
java FX VBox layout
Java Load Class Dinamically in ChildClassLoader related to SystemClassLoader

Categories

HOME
pandas
twitter
google-chrome-extension
client
google-play
vmware
cplex
adb
c#-2.0
ip
ezpublish
indesign
mouse
uber-api
python-unittest
gorm
communication
floating-action-button
leiningen
lombok
workload-scheduler
worldwind
telephony
fatal-error
http-status-code-504
jqwidget
dxf
emgucv
h2db
javacv
brunch
flink-streaming
instant-messaging
microsoft-chart-controls
sql-server-2012-express
uisplitview
catel
code-contracts
calibre
caret
hybridauth
accelerate-framework
overlap
devextreme
no-www
total-commander
thin
hibernate-tools
logparser
paxos
pnotify
veracode
rdfs
statsd
carrot
ifs
pintos
gridpane
impresspages
autorest
jwplayer7
persist
lua-5.1
python-stackless
pagerank
ios4
system.management
pervasive-sql
spidermonkey
muse
microbenchmark
dia
typekit
cdt
preferences
neolane
navigationservice
reactfx
openlaszlo
intentservice
geos
gridfs
web2py-modules
flash-builder4.5
chronoforms
xamlparseexception
plasma
sabredav
cascalog
semantic-diff
xmlspy
django-tagging
xmemcached
rfc1123
yetanotherforum
recent-documents
forums
mirah
rescale
privilege
zend-decorators
data-acquisition





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