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

How to specify the number of alphabets (and not blank spaces) to include in a substring?
spring-boot dependencies and security fixes
Achieving listview with bubble like badge on item type?
Creation of GIF is taking so long time in Android
How to send object in RequestBody as query parameters
JavaFX app icon fails to show 9/10 times
org.springframework.beans.factory.UnsatisfiedDependencyException: Unsatisfied dependency expressed through method 'anyMethodName' parameter 0:
How can I generate code using PermissionsDispatcher in Android Studio
How to unmarshal SoapFault from raw xml payload from a file?
javax.json produces uncomprehensible json
I want to start a task periodically after every 1 second no matter whether previous task ends on not
Comparing a float and its copy
Android org.apache.http.HttpResponse - which jar to include?
Jetty JDBCLoginService using null in mysql request
How to fix this error :“Method userSpaceScaleFactor in class NSWindow is deprecated on 10.7 and later”
Maven Shade - add local JAR file [duplicate]

Categories

HOME
tinymce
getelementsbytagname
cvs
spring-jdbc
sharepoint-designer
windows-server
azure-storage-tables
facebook-messenger-bot
adobe-analytics
nano-server
spring-xd
correlation
circular-dependency
n-gram
jsprit
telephony
flux
beyondcompare
viewport
emulator
accessor
mustache.php
jndi
numerical-methods
info.plist
rst2pdf
fifo
bpel
tinymce-4
ioio
siesta-swift
karaf
kendo-ui-grid
subset-sum
android-kernel
mmenu
hexo
wpf-controls
bitbucket-pipelines
xenforo
reportbuilder
sqlite2
elasticsearch-plugin
particles.js
quadratic-programming
isbn
arena-simulation
total-commander
checkboxlist
dotcover
outlook-2013
hibernate-tools
strptime
composite-key
ifs
gcsfuse
vtigercrm
background-service
messenger
root-framework
static-ip-address
libpng
url-masking
underscore.js-templating
asp.net-4.5
thrust
ctest
impresspages
simplewebrtc
ubuntu-10.04
pagerank
kendonumerictextbox
spim
dukescript
browser-bugs
dereference
modalpopup
oxwall
qpainter
gadt
cdt
mdt
rdtsc
issuu
document-classification
contenttype
comexception
algebraic-data-types
fmod
intentservice
runtime.exec
listings
jplaton
jquery-mobile-dialog
spring-validator
dsn
whoosh
fireworks
locationlistener
rfc1123
table-footer
appendto
celltable
floating
ncqrs
fixed-width
audio-capture
privilege
ubuntu-9.04

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile