Test classes needing lots of objects (Java) - java

I'm trying to write a test class for a class that has exactly one method. It's not too difficult of a method, but it does require some (my case two, through parameter) objects from upper layers. Problem is that in order to create those objects, other objects are needed and so on and so on. So I decided to write two inner class which function as placeholder classes for the two parameters, containing only the information I need. I set for these inner classes values for the attributes I'd expect in fully working circumstances.
Now Eclipse doesn't let me compile because of the following error:
The method produceTasks(IOrder, List) in the type AssemblyTaskFactory is not applicable for the arguments (AssemblyTaskFactoryTest.IOrder, List)"
As you guessed, produceTasks is the method I'm trying to test and the arguments are my inner classes. The error thrown is pretty clear about it; it won't accept my inner classes as valid parameters, despite having the same class names (because it's in fact a different class). I expected this to work if I used the same class and method names. Is there a workaround to make this work; or what would be the alternative to avoid making a hundred objects just to test one method?

MOCK dependencies and inject them during testing.
Mockito is rather nice

Related

Are instances of Class immutable?

I was wondering whether Class instances are immutable. The declared methods names do not suggest that the instance state is changed when they are invoked, but I found no explicit guarantee on the javadoc.
Scenario: I need to store unique class names in a Set. Ideally, I would like to populate the set with Class instances to avoid unnecessary calls to Class.forName() when I need to access the classe via reflection. However, it preferable to use immutable objects as keys of sets. Hence I was wondering if I could use Class instances right away.
First, The generics part Class<?> really doesn't matter here. Sure, no raw types, so Class<?> is better than Class, but for your question, the wildcard doesn't matter.
So in essence, you are asking whether Class objects are immutable. And for all practical purposes, they are.
Class objects come into existence when a class loader loads a class, and they stay put unless the whole class loader is unloaded, and everything it loaded with it.
Which can't happen when such class objects are still used in a map somewhere.
On the other hand: Class.forName() shouldn't be too expensive for classes already loaded. And when things such as serialization come into play, people suggest to go with String instead of Class objects for example (see here).
One has to distinguish between the immutable identity of a class object, and the actual "code" belonging to the class. That code can be changed at runtime (by instrumentation, think hot swap of code). But the class name, and its each code, and equals() equality should not be affected by that. Because the "identity" stays the same.
Final note: as the interesting comments below lay out, there are certain ways to alter Class objects to a certain degree. But all of these activities are definitely "out of the norm". Therefore: theoretically, you might prefer Strings over Class objects, but practically, in "normal" applications, using Class should work fine, too.
As I don’t really agree with other answer I decided to write this one,
Classes are not immutable, but they are unique - only one instance of Class object can exist for one class.
BUT class it not defined by its name, as classes might be from different class loaders, and different class loaders might have classes with same names - but that will be different classes, you would get ClassCastException if you would pass some object between code handled by 2 different class loaders if that object type would exist in both of them (as separate one, not inherited).
Class instances can be still safely used in Set, as they use default implementation of hashset/equals so only same instances of Class will be considered equals.
But to decide if you should use String or Class you need to know how exactly your app is supposed to work, as like I said, multiple classes with same name can exist between different class loaders.
And by just storing class name you can’t be sure that Class.forName will return same instance as expected it might even load some other class with same name from current class loader instead of using expected one.

Java inheritance, two-step inheritance

I have the main abstract class that is a base for bunch of classes. Some of them does not need all the fields and methods from the main abstract class, so I have created second abstract class and splitted main abstract class into two parts. The main abstract class contains, for example, a, x fields and their getters/setters, the second abstract class inherits from the main and contains additional b, c fields and their getter/setters. There are simple classes that are inheriting from the main class,and more complicated are inheriting from the second class. I want to create objects of each class as instances of the main class. Is it right way to do that? I have to type check and cast when I want to use methods from the second abstract class. It makes my code complicated. How can I solve this problem?
MainAbstractClass ---> SecondAbstractClass ---> MyComplicatedClasses
|
|
V
MySimpleClasses
One of the OO principles is Favor composition over inheritance.
This means that common behavior is not provided through base classes but via Component classes which are passed in via dependency injection (preferably as constructor parameters.
The answer depends on your actual needs.
You can instead choose to store the extended abstract class specific fields in a class that does not implement your base class and make it a member of more complicated classes.
You can choose to keep everything in a single base class and nothing forces you to use all the fields of an interface in every class that implemented your interface.
You can also keep using your approach but since you store the classes as an instance of the base class, it will be hard to read.
I believe that if you think code does not look very good, it is probably not good. However, there is usually no single answer to this kind of design questions and the best solution is relative to your preferences.
I think this need of type cast is a smell of fragile design. Here when we assume MyComplicatedClass ISA KIND OF MainAbstractClass as shown by TJ Crowder then object must behave as MainAbstractClass (meaning it can honor only API of MainAbstractClass). If it expects special treatment as MyComplicatedClass its false commitment and will need Casting. Such casting (by identifying type) goes against OO principles and kills polymorphism. Later this will end up in Ladder of InstanceOf and type casts as in the scenarios rightly pointed out by T.J. Crowder.
I would suggest readdress the design. e.g. though our all user defined type instances ARE KIND OF Object, but we use Object API only for methods defined in Object class. We do not use Object o = new MyClass(). There are occasions in frameworks or like Object.equals() method where type cast is needed as API is defined before even concrete extension is written. But it is not a good idea for such simple complete (without open hooks for extensions) Hierarchies.

Is the Method object equivalent to the Command object in the Command design pattern?

I've just discovered about the existence of the Method class in Java.
Is an instance of this class equivalent to an instance of a Command class in the context of the Command design pattern?
If not, what are this class' practical uses?
Is an instance of this class equivalent to an instance of a Command class in the context of the Command design pattern?
No, absolutely not: Method class is part of reflection feature of Java. Command pattern, on the other hand, is language-agnostic, so it can be implemented in any language, including ones that lack reflection capabilities.
The practical use of the Method class is to access methods of classes to which you do not have access at compile time. You can load a class by name, grab its method object - also by name, and perform an invocation.
With this said, it does not mean that you couldn't implement something that behaves like the command pattern using reflection. In fact, you could make your implementation more flexible by eliminating compile-time dependency on your code. For example, you could build a system that take plugins, and requires that plugin classes implement a particular method. Rather than shipping to plugin writers an interface with the signature of the method, you could tell them that as long as their class implements the method that you need, the plugin is going to be accepted. At runtime you would be able to discover the proper method through reflection, and call user code without compile-time dependencies on either side.
This class, as well as the class Field, class Class, are all part of reflection API. This API is used to provide access to object in an indirect way.
The first idea behind reflection was to allow an object to describe itself. For instance an IDE could display all properties of an object for debugging, RAID development and so on.
If reflection is still used that way, it's also used today to discover dynamically the structure of an object or a class and "act on" it without explicitly knowing it : to change the values of its fields or invoke one its methods.
For instance, if you know class A, you can invoke the method m() of A this way :
A a = new A();
a.m();
With reflection, without knowing class A explicitly, you could :
Object a = A.getDeclaredConstructors()[0].newInstance();
Method m = a.getClass().getMethod("m");
m.invoke(a, null);
In the second case, you can imagine a more generic mechanism where you discover methods or fields and invoke them or change their values without knowing them in advance.
So, to answer directly your question, it has nothing to do with the Command design pattern.

Junit multiple inputs/multiple methods testing via #Parameters

I'm relatively new to JUnit 4; I have figured out that I can repeat the same test over a method, with different inputs, using #Parameters annotation to tag a method returning an Iterable of arrays, say a List<Integer[]>.
I found out that JUnit does require the method provider of Iterable of arrays to be static and named data, which means that you can test different methods but using always the same data.
As a matter of fact you can tag any method (with any return type, BTW) with #Parameters, but with no effect; only data() method is taken into account.
What I was hoping JUnit allowed to do was having some different data sets annotated with #Parameters and some mechanism (say an argument to #Test) which could specify to use data set X while performing testFoo() and data set Y for testBar().
In other words I would like to set up a local (as opposed to class/instance) data set in each of my testing methods.
As I understand the whole thing, you are obliged to build a separate class for each of the methods you want to test with multiple inputs, which IMHO makes the thing pretty useless; AAMOF I built myself a modest framework (actually based on JUnit) which indeed allows me multiple methods testing with multiple inputs (with tracing feature), all contained in a single class, avoiding so code proliferation.
Am I missing something ?!?
It shouldn't matter what the method is called, as long as it has the #Parameters annotation.
The easiest way to have multiple datasets is to put the tests in an abstract class and have the concrete subclasses have the method with the #Parameters method.
However, I would question why one would want to have multiple datasets per test in the same test class. This probably violates the single responsibility principle and you should probably break the data sets into 1 test class each.

trying to use only one method name

When I was programming a Form Validator in PHP, when creating new methods, I needed to increase the number of arguments in old methods.
When I was learning Java, when I read that extends is to not touch previously tested, working code, I thought I shouldn't have increased the number of arguments in the old methods, but overridden the old methods with the new methods.
Imagine if you are to verify if a field is empty in one part of the form, in an other and in yet an other.
If the arguments are different, you'll overload isEmpty, but, if the arguments are equal, is it right to use isEmpty, isEmpty2, isEmpty3, three classes and one isEmpty per class or, if both are wrong, what should I have done?
So the question is:
If I need different behaviors for a method isEmpty which receives the same number arguments, what should I do?
Use different names? ( isEmpty, isEmpty2, isEmpty3 )
Have three classes with a single isEmpty method?
Other?
If that's the question then I think you should use:
When they belong to the same logical unit ( they are of the same sort of validation ) but don't use numbers as version, better is to name them after what they do: isEmptyUser, isEmptyAddress, isEmptyWhatever
When the validator object could be computed in one place and passed around during the program lifecycle. Let's say: Validator v = Validator.getInstance( ... ); and then use it as : validator.isEmpty() and let polymorphism to it's job.
Alternatively you could pack the arguments in one class and pass it to the isEmpty method, although you'll end up with pretty much the same problem of the name. Still it's easier to refactor from there and have the new class doing the validation for you.
isEmpty( new Arguments(a,b,c ) ); => arguments.isEmpty();
The Open/Closed Principle [usually attributed to Bertrand Meyer] says that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". This might be the principle that you came across in your Java days. In real life this applies to completed code where the cost of modification, re-testing and re-certification outweighs the benefit of the simplicity gained by making a direct change.
If you are changing a method because it needs an additional argument, you might choose to use the following steps:
Copy the old method.
Remove the implementation from the copy.
Change the signature of the original method to add the new argument.
Update the implementation of the original method to use the new argument.
Implement the copy in terms of the new method with a default value for the argument.
If your implementation language doesn't support method overloading then the principle is the same but you need to find a new name for the new method signature.
The advantage of this approach is that you have added the new argument to the method, and your existing client code will continue to compile and run.
This works well if there is an obvious default for the new argument, and less well if there isn't.
Since java 5 you can use variable list of arguments as in void foo(Object ... params)
You will need to come up with creative names for your methods since you can't overload methods that have same type and number of arguments (or based on return type). I actually personally prefer this to overloading anyway. So you can have isEmpty and isEmptyWhenFoo and isEmptyWhenIHaveTheseArguments (well meybe not the last one :)
Not sure if this actually answers your question, but the best way to think about OO in "real life" is to think of the Nygaard Classification:
ObjectOrientedProgramming. A program execution is regarded as a physical model, simulating the behavior of either a real or imaginary part of the world.
So how would you build a physical device to do what you are trying to do in code? You'd probably have some kind of "Form" object, and the form object would have little tabs or bits connected to it to represent the different Form variables, and then you would build a Validator object that would take the Form object in a slot and then flash one light if the form was valid and another if it was invalid. Or your Validator could take a Form object in one slot and return a Form object out (possibly the same one), but modified in various ways (that only the Validator understood) to make it "valid". Or maybe a Validator is part of a Form, and so the Form has this Validator thingy sticking out of it...
My point is, try to imagine what such a machine would look like and how it would work. Then think of all of the parts of that machine, and make each one an object. That's how "object-oriented" things work in "real life", right?
With that said, what is meant by "extending" a class? Well, a class is a "template" for objects -- each object instance is made by building it from a class. A subclass is simply a class that "inherits" from a parent class. In Java at least, there are two kinds of inheritance: interface inheritance and implementation inheritance. In Java, you are allowed to inherit implementation (actual method code) from at most one class at a time, but you can inherit many interfaces -- which are basically just collections of attributes that someone can see from outside your class.
Additionally, a common way of thinking about OO programming is to think about "messages" instead of "method calls" (in fact, this is the original term invented by Alan Kay for Smalltalk, which was the first language to actually be called "object-oriented"). So when you send an isEmpty message to the object, how do you want it to respond? Do you want to be able to send different arguments with the isEmpty message and have it respond differently? Or do you want to send the isEmpty message to different objects and have them respond differently? Either are appropriate answers, depending on the design of your code.
Instead having one class providing multiple versions of isEmpty with differing names, try breaking down your model into a finer grained pieces the could be put together in more flexible ways.
Create an interface called Empty with
one method isEmpty(String value);
Create implemntations of this
interface like EmptyIgnoreWhiteSpace
and EmptyIgnoreZero
Create FormField
class that have validation methods
which delegate to implementations of
Empty.
Your Form object will have
instances of FormField which will
know how to validate themselves.
Now you have a lot of flexibility, you can combine your Empty implemenation classes to make new classes like EmptyIgnoreWhiteSpaceAndZero. You can use them in other places that have nothing to do with form field validation.
You don't have have have multple similarly named methods polluting your object model.

Categories

Resources