Imagine you have an application and you want to make unit tests and functionnal tests over it (not quite hard to imagine). You might have an abstract class, let's call it AbstractTestClass, from which all your unit tests extends.
AbstractTestClass would look something like this (using JUnit 4) :
class AbstractTestClass {
boolean setupDone = false;
#Before
public void before() {
if(!setupDone) {
// insert data in db
setupDone = true;
}
}
}
Here is what I'm struggling with. I'm having another abstract class which test the web interfaces :
class AbstractWebTestClass extends WebTestCase {
boolean setupDone = false;
#Before
public void before() {
if(!setupDone) {
// here, make a call to AbstractTestClass.before()
// init the interfaces
setupDone = true;
}
// do some more thing
}
}
It's pretty much the same class, except that it extends WebTestCase. This design could give me the possibility to have the same data while unit testing than when testing the interface.
Usually, when dealing with such issue, you should favor composition over inheritance or use a strategy pattern.
Unfortunately, I don't quite like the idea to favor composition over inheritance in this particular scenario and I don't see how I could use a strategy pattern, there is probably a design flaw and I can't quite see the solution.
How could I design this architecture in order to achieve my goal.
I would implement this in the following way:
class Example {
class LazyInitStrategy implements Runnable {
private final Runnable operation;
private boolean done = false;
LazyInitStrategy(Runnable operation) {
this.operation = operation;
}
#Override
public void run() {
if (!done) {
operation.run();
done = true;
}
}
}
private final class AbstractInit implements Runnable {
public void run() {
// insert data in db
}
}
private final class AbstractWebInit implements Runnable {
public void run() {
// here, make a call to AbstractTestClass.before() init the interfaces
}
}
class AbstractTestClass {
final LazyInitStrategy setup = new LazyInitStrategy(new AbstractInit());
#Before
public void before() {
setup.run();
// do some more thing
}
}
class AbstractWebTestClass extends WebTestCase {
final LazyInitStrategy setupInfo = new LazyInitStrategy(new AbstractWebInit());
#Before
public void before() {
setupInfo.run();
// do some more thing
}
}
}
Sure this is very simplistic solution but it should eliminate if/else logic duplication for checking if setup was done. Using Runnable is optional, I did this just for demo purposes, in read world you probably will use another interface.
The important thing to accomplish is not to duplicate code. In this situation I would create a
MyScenarioTestUtil
class that has a bunch of static methods on it that sets up the data as you need to. You would invoke the utility methods from the setup. That way you keep all the code in one place.
Its really just a semantics difference from using composition...
I think that the design is wrong in general. You shouldn't use inheritance in unit tests at all. Tests should be isolated and really plain. Very often, like in your case, it's necessary to prepare some supplementary objects, that will help test methods to do their job. In such a case you should define builders of such objects, and place them somewhere outside of test cases.
For example:
public void testMethodThatNeedsSomePreparedObjects() {
Foo foo = new FooBuilder()
.withFile("some-text.txt")
.withNumber(123)
.build();
// now we are testing class Bar, using object of class Foo
Bar bar = new Bar(foo);
}
Thus, you need FooBuilder to be defined somewhere else, and this class will do all the work you're now trying to do using stategy pattern or inheritance. Both approached are wrong, when dealing with unit tests.
Related
I do have a service which needs to handle two types of meal.
#Service
class MealService {
private final List<MealStrategy> strategies;
MealService(…) {
this.strategies = strategies;
}
void handle() {
var foo = …;
var bar = …;
strategies.forEach(s -> s.remove(foo, bar));
}
}
There are two strategies, ‘BurgerStrategy’ and ‘PastaStrategy’. Both implements Strategy interface with one method called remove which takes two parameters.
BurgerStrategy class retrieves meals of enum type burger from the database and iterate over them and perform some operations. Similar stuff does the PastaStrategy.
The question is, does it make sense to call it Strategy and implement it this way or not?
Also, how to handle duplications of the code in those two services, let’s say both share the same private methods. Does it make sense to create a Helper class or something?
does it make sense to call it Strategy and implement it this way or not
I think these classes ‘BurgerStrategy’ and ‘PastaStrategy’ have common behaviour. Strategy pattern is used when you want to inject one strategy and use it. However, you are iterating through all behaviors. You did not set behaviour by getting one strategy and stick with it. So, in my honour opinion, I think it is better to avoid Strategy word here.
So strategy pattern would look like this. I am sorry, I am not Java guy. Let me show via C#. But I've provided comments of how code could look in Java.
This is our abstraction of strategy:
public interface ISoundBehaviour
{
void Make();
}
and its concrete implementation:
public class DogSound : ISoundBehaviour // implements in Java
{
public void Make()
{
Console.WriteLine("Woof");
}
}
public class CatSound : ISoundBehaviour
{
public void Make()
{
Console.WriteLine("Meow");
}
}
And then we stick with one behaviour that can also be replaced:
public class Dog
{
ISoundBehaviour _soundBehaviour;
public Dog(ISoundBehaviour soundBehaviour)
{
_soundBehaviour = soundBehaviour;
}
public void Bark()
{
_soundBehaviour.Make();
}
public void SetAnotherSound(ISoundBehaviour anotherSoundBehaviour)
{
_soundBehaviour = anotherSoundBehaviour;
}
}
how to handle duplications of the code in those two services, let’s say both share the same private methods.
You can create one base, abstract class. So basic idea is to put common logic into some base common class. Then we should create abstract method in abstract class. Why? By doing this, subclasses will have particular logic for concrete case. Let me show an example.
An abstract class which has common behaviour:
public abstract class BaseMeal
{
// I am not Java guy, but if I am not mistaken, in Java,
// if you do not want method to be overriden, you shoud use `final` keyword
public void CommonBehaviourHere()
{
// put here code that can be shared among subclasses to avoid code duplication
}
public abstract void UnCommonBehaviourShouldBeImplementedBySubclass();
}
And its concrete implementations:
public class BurgerSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
public class PastaSubclass : BaseMeal // extends in Java
{
public override void UnCommonBehaviourShouldBeImplementedBySubclass()
{
throw new NotImplementedException();
}
}
I have just started learning JUnit very recently and came across the following problem.
Have a look at the following class
class MyClass {
String a;
public MyClass(String a) {
this.a=a;
String doSomething(String a) {
if( a.isEmpty() )
return "isEmpty";
else
return"isNotEmpty";
}
I want to test the above method for both the conditions. If I proceed with the general structure of writing testcases it will look something like this:
class MyClassTest {
MyClass myClass;
#BeforeEach
void setUp() {
myClass=new MyClass("sampleString");
}
#Test
void doSomethingTest() {
Assertions.equal("isNotEmpty", myClass.doSomething());
}
}
However, for testing the empty string condition I will need another setup method where instead of "sampleString" I pass an empty string.
Following are the approaches I could think of and the questions for each:
Not use setUp at all and instead initialize the class in the individual test method. However, if let's say there are 10 testcases; 5 of which require empty string and rest "sampleString" then this doesn't make sense. Again, we can have a separate method for this repetitive code and call it individually in each testcase but then that defeats the purpose of having a steup method. Lets say I wanted to use two different setup methods, is there a way to do so?
Have a parameterized setup. I don't know if this is possible though. If yes, please share some useful links for this.
Use TestFactory. I tried reading up about this, but couldn't find an example for this specific case. If you have any, please share.
This example has been kept simple for illustrative purposes.
Group the tests with the same setup in an inner class annotated with #Nested. Each nested test class can have its own setup in a local #BeforeEach method.
You can always prepare the non-common data inside your test method. I've always thought it's easier this way, compared to using parameterized tests. You can't mix parameterized and non-parameterized tests in 1 file.
#Test
void doSomething_nullString()
{
myClass = new MyClass(null);
Assert.assertNull(myClass.doSomething());
}
#Test
void doSomething_emptyString()
{
myClass = new MyClass("");
Assert.assertEquals("", myClass.doSomething());
}
#Test
void doSomething_nonEmptyString()
{
myClass = new MyClass("sampleString");
Assert.assertEquals("sampleString", myClass.doSomething());
}
Or, you can always have helper methods inside the test class.
private MyClass createTestObject_nonNullString() {
return new MyClass("nonNullString");
}
private MyClass createTestObject_nullString() {
return new MyClass(null);
}
#Test
public void doSomething_sample() {
MyClass test = createTestObject_nonNullString();
// perform test
}
I have a class similar to this:
public class QueueingCommandRunner {
private Status status;
private Map<Class<CommandHandler>, CommandHandler> queuedCommands;
private RunnerClass runnerClass;
private ExternalCommandRunnerRegistry externalCommandRunnerRegistry;
private ExternalCommandRunner externalCommandRunner;
public QueueingCommandRunner(ExternalCommandRunnerRegistry externalCommandRunnerRegistry,
RunnerClass runnerClass) {
this.externalCommandRunnerRegistry = externalCommandRunnerRegistry;
this.runnerClass = runnerClass;
this.queuedCommands = new LinkedHashMap<>();
this.status = Status.DOWN;
}
public void init() {
doSomeStuff();
externalCommandRunner = externalCommandRunnerRegistry.get(runnerClass);
externalCommandRunner.runListeningCommand(ListenableStatusCommand.class,
new ListenableStatusHandler(this::changeStatus));
}
public <T extends CommandHandler> void runCommand(Class<T> command, T commandHandler) {
if (status == UP) {
externalCommandRunner.run(command, commandHandler);
} else {
queuedCommands.put(command, commandHandler);
}
}
private void changeStatus(Status status) {
this.status = status;
if (status == UP) {
Iterator<Entry<Class<CommandHandler>, CommandHandler>> commandsIterator =
queuedCommands.iterator();
while (commandsIterator.hasNext()) {
<Entry<Class<CommandHandler>, CommandHandler>> queuedCommand = commandsIterator.next();
externalCommandRunner.run(queuedCommand.getKey(), queuedCommand.getValue());
commandsIterator.remove();
}
}
}
}
I omit stuff like synchronization. My question is, how to test queuing which is inside without using things like invocation of private methods via reflection? In particular I would like to know how to test changeStatus method since it is not directly run from any public method in this class. Is this class bad by design (from unit testing point of view)?
I am using JMockit for testing...
As it was mentioned in the comment - you test
desired public observable behavior
So, if you want to test private methods you need to make them public. I suggest to make it as interface:
public interface SomeInterface {
changeStatus(Status status);
}
Then inject implementation to your class:
public final class A {
private final SomeInterface someInterface;
public A(SomeInterface someInterface) {
this.someInterface = someInterface;
}
}
Then you can easily test SomeInterface implementation and mock if you need it in your class A.
So, I cannot give you the whole refactoring process for your particular case. But you can follow this guideline and you can encapsulate all private methods with interfaces that are tested easily. As I can see, you are using internal details of your class in private methods - these details should be encapsulated in interface implementation constructor (via another interfaces) and you will end up with small nice cohesive testable classes. Look through Command Pattern as it seems suitable for your case and try to follow SOLID which will also lead to testable code.
I see several problems with your design:
init() method. Which leads to temporal coupling as your class is not ready to use after construction;
your runCommand method is doing two things based on status. It's either run command or put it to map (which is hidden side-effect);
your changeStatus is also running comands.
You need to decouple those thins (running command, holding them and tracing status). Maybe encapsulate status of the command inside command itself. So the command will know how to work in its own way.
I have a suite of unit tests. I have a static variable which gets initialized in setup() method. I want to run all my suite of unit tests with two different values of that static variable.
Static variable in setup() gets initialized to an object which is a singleton. So, I can't(I think I can't) use JUnit parametrized tests.
I have to run all the tests with one value of that static variable, and then run all the tests with other value of static variable.
Any ideas on how to do this in an elegant way if possible.
Code below if my description above is not very easy to understand
public class MyClassTest{
private static final Dep_class dep_obj;
public static void setup(){
dep_obj = Dep_class.getInstance("VALUE_1");
//You can have only instance of Dep_class at any time.
//So for second run I need to do a
//dep_obj = Dep_class.getInstance("VALUE_2") and run my tests.
}
public void test_mymethod(){
//do something with dep_obj
}
Try this
#RunWith(Parameterized.class)
public class MyClassTest {
private Object dep_obj;
public MyClassTest(String val) {
dep_obj = val;
}
#Parameters
public static Collection<?> data() {
Object[][] data = { { "val1" }, { "val2" }, { "val3" } };
return Arrays.asList(data);
}
#Test
public void test() {
System.out.println(dep_obj);
}
}
So first of all, I would question why you have a singleton that is initialized in this way. It seems as if adding an argument to your .getInstance(String s) method would add ambiguity and unexpected behavior, as this String argument will just be disregarded after instantiation (unless you're re-instantiating it if the type changes, in which case it will be highly unpredictable at runtime).
In any case, an easy way to do this would be to abstract the test_mymethod() to a parent class and have two child test classes that each instantiate a different instance of the singleton. Since your JVM will not restart, you'll also need something like PowerMock to reset the singleton to a pre-loaded state before running any tests.
So the parent class would look like so (JUnit annotations added):
public abstract class MyAbstractTestClass {
private final Dep_class dep_obj;
#Before
public abstract void setup(){
// Begin by ensuring that the singleton instance is initialized to null -
// this is highly important, since subclasses will not be able to rely on
// an un-initialized state
Whitebox.setInternalState(dep_obj.getInstance(/*default, arbitrary, or null value*/, "instance", null);
// Now leave the actual singleton initialization to child classes
dep_obj = getSingleton();
}
public abstract Dep_class getSingleton();
#Test
public void test_mymethod(){
//do something with dep_obj
}
}
I made a few assumptions with Powermock - namely that your singleton properly checks to see if the instance is null and if so, initializes it. In this case, I'm assuming that the variable name for your instance is "instance". Next, your child classes would look like this:
public class MyTestClass1 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_1");
}
}
public class MyTestClass2 extends MyAbstractTestClass {
#Override
public void Dep_class getSingleton() {
return Dep_class.getInstance("VALUE_2");
}
}
Again, I would strongly encourage you to re-think implementing a singleton in this way. Singletons should be rarely used anyway - an implementation like this on top of a questionable design pattern is an eyebrow raiser. This question goes over some good guidelines for usage - make sure that your singleton fits this criteria.
I have an adapter from I1 to ILogger implemented like this:
class BAdapter() implements I1
{
void logA() { // nothing }
void logB() { new BLogger().log() }
void logC() { // nothing }
}
I would like to write JUnit test, that verify the functionality, but I found it a bit problematic, since I cannot inject my Mock object instead of BLogger, or verify return value. I found several possible solution, but I am not sure, which is the best.
Case One:
Add void setLogger(Logger l) to the BAdapter class.
class BAdapter() implements I1
{
private Logger logger = new BLogger();
public void logB() { logger.log() }
public void setLogger(Logger l) { logger = l }
.. //rest of methods
}
Cons: Why to add setter which is never used in "real", non-testing code?
Case Two:
Add protected factory method and sublcass BAdapter in test package.
class BAdapter() implements I1
{
public void logB() { createLogger().log() }
protected Logger createLogger() { retrun new BLogger() }
.. //rest of methods
}
class BAdapterForTesting extends BAdapter()
{
protected Logger createLogger() { retrun new MockBLogger() }
}
Cons: I am not sure, if this is clean and elegant solution, but I don't see much cons here.
Case Three:
Use Abstract Factory pattern.
class BAdapter() implements I1
{
public void logB() { AbstractFactory.getFactory().getBLogger().log() }
.. //rest of methods
}
And somewhere in tests:
AbstractFactory.setFactory(new MockLoggersFactory())
Cons: This is too complex, isn't it?
Case Four:
Return Boolean, for example, when logging was performed. E.g.
class BAdapter() implements I1
{
Boolean logA() { return false; }
Boolean logB() { return new BLogger().log() }
Boolean logC() { return false; }
}
Cons: This is kind of wourkaround. Why to return some value, when nobody needs it in "real", non-testing code?
Better Solution?
Is there anything better?
From your code it's hard to tell exactly what the class under test is trying to achieve but
I'd go with Case One with the caveat that I'd use injection in the 'real' code too.
One of the benefits of injection is it makes the class, in this case your adapter, more re-usable. Forcing the logB method to always delegate to an instance of BLogger sets that behaviour in stone at compile time. If I want the adapter to delegate to another type of Logger I can't use it and it is therefore slightly less re-usable.
IMVHO creating code especially to be used by tests and nowhere else is not a good idea as it may expose functionality that is not supposed to be used, yet some may think using it is cool and be badly surprised.
This leaves us with case 3 which is a generally very good approach, yet if it is only to be used during testing its still a bit of overkill.
I'd suggest using some additional mocking framework like PowerMock which can change private fields in classes in convenient way:
class BAdapter() implements I1
{
private Logger logger = new BLogger();
public void logB() { logger.log() }
.. //rest of methods
}
and then during testing swap the field to some mock:
Whitebox.setInternalState(loggerInstance, "logger", new MockLogger());
more info:
http://code.google.com/p/powermock/wiki/BypassEncapsulation
Mocking frameworks are great asset during testing so knowing them helps a lot.