I am refactoring a Hibernate mapped object Gadget to remove getIntFieldValue and setIntFieldValue and changing my code to retrieve that value from a DAO object, which is created using a Factory and to which a Gadget is passed.
public class GadgetPropertyAccessFactory {
public static GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
}
...
The test code looks like this:
//this mocks a Gadget
Gadget gadget = createGadget();
//this is to be replaced
when(gadget.getIntFieldValue()).thenReturn(2);
DoerClass doerClass = new DoerClass(null, gadget);
List<Result> doerResults = doerClass.produceResults();
for (Result doerResult : doerResults) {
//...
}
The DoerClass looks something like this
Session dbSessn;
Gadget gadget;
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
//this is to be replaced
int intFieldValue = this.gadget.getIntFieldValue()
//with
//GadgetPropertyDAO gadgPropDAO = GadgetPropertyAccessFactory.getGadgetPropertyDAO(this.dbSessn);
//int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
//generate List<Result> based on intFieldValue
}
My problem is that before I was able to conveniently mock what getIntFieldValue will return in produceResults but now that I am using a statically returned DAO, I do not know if it is possible to mock what GadgetPropertyDAO.getDeviceIntFieldValue(this.gadget) will return.
Is a mock possible without changing my method signatures (API)?
I agree with Tom G: Mockito and dependency injection (and arguably Java itself) are really designed for instances much more than static methods—it's the only way to take advantage of Java's polymorphic advantages. If you switch to making your factory an instance, it would look like this:
public class GadgetPropertyAccessFactory {
public GadgetPropertyDAO getGadgetPropertyDAO(Session dbSessn){
if(getSomeBooleanFromDB(dbSessn)) {
return new TrueImplGadgetPropertyDAO();
} else {
return new FalseImplGadgetPropertyDAO();
}
} // ...
}
public class DoerClass {
Gadget gadget;
Session dbSessn;
// Sets default implementation. Constructor injection would also work.
GadgetPropertyAccessFactory gpaFactory = new GadgetPropertyAccessFactory();
public DoerClass(Session dbSessn, Gadget gadget) {
this.dbSessn = dbSessn;
this.gadget = gadget;
}
public List<Result> produceResults() {
GadgetPropertyDAO gadgPropDAO =
gpaFactory.getGadgetPropertyDAO(this.dbSessn);
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
}
// in your test
DoerClass doerClass = new DoerClass(null, gadget);
GadgetPropertyAccessFactory mockFactory =
Mockito.mock(GadgetPropertyAccessFactory.class);
doerClass.gpaFactory = mockFactory;
// ...
Another option is to live with and manage your testing gap:
public List<Result> produceResults() {
return produceResultsInternal(gpaFactory.getGadgetPropertyDAO(this.dbSessn));
}
/** Visible only for testing. Do not call outside of tests. */
List<Result> produceResultsInternal(GadgetPropertyDAO gadgPropDAO) {
int intFieldValue = gadgPropDAO.getDeviceIntFieldValue(this.gadget);
// ...
}
...which then allows you to test against produceResultsInternal with a mock, which gets you 80% tested with 20% of the grief.
Related
I have this code
private final Map<String, ReEncryption> reEncryptionInstances =
new HashMap<>();
public ReEncryption getReEncryptionLibInstance ()
throws ReEncryptionException
{
final String schemaName = getSchemaName();
final ReEncryption reEncryption = reEncryptionInstances.get(schemaName);
if (reEncryption != null) {
return reEncryption;
}
createReEncryptionLibInstance();
if(reEncryptionInstances.get(schemaName) == null) {
throw new ReEncryptionException(ERROR_LIBRARY_NOT_INITIALIZED);
}
return reEncryptionInstances.get(schemaName);
}
ReEncryptionInstances is a Hashmap and i want to set reEncryptionInstances.get(schemaName) == null to test my if block. How can i do that in my test class?
I can see two approaches here:
Wrap that reEncryptionInstances into a different class
Partially mock the class under test, so the createReEncryptionLibInstance does not do anything.
Option #1 would look like this:
public class YourClassUnderTest {
private final EncryptionInstances reEncryptionInstances;
public YourClassUnderTest(EncryptionInstances reEncryptionInstances) {
// You can do it in a setter too
// You can inject a Map too
this.reEncryptionInstances = reEncryptionInstances;
}
// ...
}
//...
/**
* You can also mock the EncryptionInstances class.
*/
public class TestEncryptionInstances extends EncryptionInstances {
public ReEncryption getEncryption(String schemaName) {
return null;
}
//...
}
Option #2 is generally a bad practice. So I am just pointing to Mockito.spy() and partial mocking.
I'm trying to pass new Object as method parameter and set it's variable at the same time.
This an okay solution but big and not nice...
EventBox evtbox = new EventBox();
evtbox.setFloorColor(floorColor);
scriptUtils.runScript("sc-cfrmd",evtbox);
and I need something like this to shorten it up a bit
scriptUtils.runScript("sc-cfrmd",new EventBox().setFloorColor(floorColor));
of course, logical way of doing this is just creating a constructor in EventBox class but I need to figure out way without use of constructors.
any tips are appreciated
You are looking for fluent interface
Usually, when you need to create a complex object you are implementing fluent interface with builder design pattern
For example:
import java.awt.Color;
public class EventBox {
private Color floorColor;
private EventBox() {
this.floorColor = null;
}
public Color getFloorColor() {
return floorColor;
}
private void setFloorColor(Color floorColor) {
this.floorColor = floorColor;
}
public static EventBoxBuilder builder() {
return new EventBoxBuilder();
}
public static class EventBoxBuilder {
private final EventBox box;
EventBoxBuilder() {
this.box = new EventBox();
}
public EventBoxBuilder setFloorColor(Color color) {
box.setFloorColor(color);
return this;
}
public EventBox build() {
return box;
}
}
}
....
scriptUtils.runScript("sc-cfrmd",EventBox.builder().setFloorColor(floorColor).build());
If you are able to use Lombok Framwork, such builder can be automatically generated on compile time by adding #Builder annotation to the EventBox class
You can use method chaining by adding methods as desired. Conventionally, leave the setters/getters as the standard practice to just do what their name says.
public EventBox withFloorColor(String floorColor) {
setFloorColor(floorColor);
return this;
}
scriptUtils.runScript("sc-cfrmd",new EventBox().withFloorColor(floorColor));
The most basic and simple solution is of course to create a method like
EventBox createFloorEventBox( String floorColor ) {
EventBox eb = new EventBox();
eb.setFloorColor( floorColor );
return eb;
}
and use it like
scriptUtils.runScript("sc-cfrmd", createEventBox( floorColor ) );
Besides the builder pattern/method chaining/fluent approach, you could also consider using lambdas in Java, like
void runScript(String something, Consumer<EventBox> boxInitializer) {
EventBox eb = new EventBox();
initializer.apply(eb);
...
}
and then call this like
runScript("something", eb -> eb.setFloorColor( floorColor ));
I have the following object structure:
class Annotation;
class LabelAnnotation: inherits Annotation;
class TextAnnotation: inherits LabelAnnotation;
I would like to use "creator" objects to do some initialization on these object (This initialization depends on external settings so I don't want to do it in the constructor of these objects.)
In particular, when creating a LabelAnnotation I would like to do:
fontSize = AppDefaults.fontSize
So I'm writing a "creator":
class LabelAnnotationCreator {
LabelAnnotation create() {
annotation = LabelAnnotation()
annotation.fontSize = AppDefaults.fontSize
return annotation;
}
}
Now, I would like to create a TextAnnotationCreator. This is where I'm stuck: I can't use the LabelAnnotationCreator because it would create an instance of a LabelAnnotation, but on the other hand, I want to benefit from the initialization performed by the LabelAnnotationCreator.
class TextAnnotationCreator {
TextAnnotation create() {
annotation = TextAnnotation()
// I'm stuck here:
// can't do LabelAnnotationCreator().create()… ???
return annotation;
}
}
Obviously, this isn't the right pattern but I'm not sure how to find the correct one.
Thanks!
what do you think about this:
class TextAnnotation {
private final int someOtherArgs;
private final int fontSize;
public TextAnnotation(LabelAnnotation labelAnnotation, int someOtherArgs) {
this(someOtherArgs, labelAnnotation.getFontSize());
}
public TextAnnotation(int someOtherArgs, int fontSize) {
this.someOtherArgs= someOtherArgs;
this.fontSize = fontSize;
}
}
create a constructor on TextAnnotation that builds a object from a LabelAnnotation configuration. Then you can use it like this:
TextAnnotation text = new TextAnnotation(someArgs,fontSize);
or using your creator
class TextAnnotationCreator {
TextAnnotation create() {
return
new TextAnnotation(
new LabelAnnotationCreator().create(),
someOtherArgs
);
}
}
I'm using Mockito to mock a method to return a Date when given a Date.
when(supplier.calculateDeliveryDate(any(Date.class)))
.thenReturn(supplierDeliveryDate);
However, I only want it to return the supplierDeliveryDate when it is passed a non-null Date object.
When passed null, it should return null.
Is this possible? How can I do it?
Use ArgumentMatchers.isNull() matcher.
when(supplier.calculateDeliveryDate(any(Date.class)))
.thenReturn(supplierDeliveryDate);
when(supplier.calculateDeliveryDate(isNull()))
.thenReturn(null);
You could use an anonymous inner class:
// unit test
public OrderServiceTest {
// instance of class-under-test
private OrderService instance;
// stub value
private Date supplierDeliveryDate = new Date();
// mock as an anonymous inner class
private Supplier supplier = new Supplier() {
public Date calculateDeliveryDate(Date input) {
if (input == null) {
return null;
}
else {
return supplierDeliveryDate;
}
}
};
#Before
public void setUp() {
instance = new OrderService();
// dependency injection
instance.setSupplier(supplier);
}
#Test
public void testOrderHappy() {
// SETUP
Date orderDate = new Date();
// CALL
Date result = instance.order(orderDate);
// VERIFY
assertTrue(supplierDeliveryDate == result);
}
#Test
public void testOrderNull() {
// SETUP
Date orderDate = null;
// CALL
Date result = instance.order(orderDate);
// VERIFY
assertNull(result);
}
}
But you should really wonder why you need this kind of behavior.
If you write a well defined test case then you should know exactly how often, and with which arguments, your mock is called. If so, then you can just stub the expected calls instead of wiring your mock with conditional behavior.
Note that is is useful if your test is as 'sharp' as possible. If a different number of calls hits your mock than expected, or with different arguments, then the test should fail.
You can use helper method:
public static <T> void validateAndMock(Supplier<T> ongoingStubbing, T mockedResponse) {
if (mockedResponse != null) {
when(ongoingStubbing.get()).thenReturn(mockedResponse);
}
}
And then call:
validateAndMock(() -> supplier.calculateDeliveryDate(any(Date.class)), supplierDeliveryDate);
I have an object which is created on the basis of few conditions, like this -
if (objType.equals("one-type")) {
targetTableName = "one_type_table";
sourceTableName = "one_type_parent";
unitTime = 1;
delayTime = 10;
} else if (objType.equals("two-type")) {
targetTableName = "two_type_table";
sourceTableName = "two_type_parent";
unitTime = 2;
delayTime = 20;
}
Config databaseConfig = new Config(targetTableName, sourceTableName, unitTime, delayTime);
I have been told that my module has to be saved from this monstrosity and the pattern that can save me is Factory. So I decided to use that and create an interface like this -
public interface ConfigInterface {
public String getSourceTable();
public String getTargetTable();
public int getDelay();
public int getUnitTime();
}
and also created a concrete implementation of this interface called Config.
Then create a factory to build this object -
public class ConfigFactory {
public ConfigInterface getConfig (String objType) {
if (objType.equals("one-type")) {
targetTableName = "one_type_table";
sourceTableName = "one_type_parent";
unitTime = 1;
delayTime = 10;
} else if (objType.equals("two-type")) {
targetTableName = "two_type_table";
sourceTableName = "two_type_parent";
unitTime = 2;
delayTime = 20;
}
Config databaseConfig = new Config(targetTableName, sourceTableName, unitTime, delayTime);
return databaseConfig;
}
}
Now I just shifted my monster code inside another function. Even that is fine but my config interface is not really a superclass for many subclasses which are being generated by factory class. There is only one type of Config object, it has all those 5 fields and thats it.
I am sure I am either using it wrong or its not the right solution for this problem. Can anyone tell me whats wrong or is there another magical pattern to solve my problem and get me those ship its.
Why not encapsulate Config subclasses OneType and TwoType that set these values in their constructor. Then change the factory to the following:
public Config getConfig (String objType) {
if (objType.equals("one-type")) {
return new OneType ();
} else if (objType.equals("two-type")) {
return new TwoType ();
}
Alternatively, I use this pattern with enums for this kind of situation:
enum ConfigType {
one-type ("one_type_table", "one_type_parent", 1, 10),
two-type ("two-type_table", "two_type_parent", 2, 20)
;
ConfigType (String table, String parent, int unit, int delay) {
...
}
String getTable () {
return this.table;
}
....
}
Now you can generalize the factory code and work in terms of static enum types instead of runtime evaluated strings.
public Config getConfig (ConfigType type) {
return new Config (type.getTable (),...
The size of the code in the question is small, so any implementation would be as efficient as the other.
If the objType comes from different class instances, say TypeOne and TypeTwo, then you could overload the getConfig() method, e.g.
public ConfigInterface getConfig(TypeOne type)
{
// Create and return the "one-type" object
}
public ConfigInterface getConfig(TypeTwo type)
{
// Create and return the "one-type" object
}
Otherwise, especially if there are many different types, consider creating an enum with all the possible values to objType, as opposed to using a string. You can then use a switch statement, which is more efficient than the consecutive string equals checks.