Correct way to design and test this class - java

I am developing an interpreter and want to do internal testing of an "execute" method that interprets a model. The execute method doesn't have input or output, so the only way to test the method (at least from what I know) is to mock the internal method calls to see that they are executed in the right order.
Currently I have the following classes:
ExecutableInstance - model class that can be executed.
ExecutableInstanceFactory - singleton class (implemented as an enum) that creates executable instances, with different methods depending on the parameters it is given.
ModelAnalyzer - singleton class that contains methods to analyze the model
The interpreter calls the execute() method of the ExecutableInstance class, which then calls the ModelAnalyzer to understand the internal executable instances in the model. It then creates new ExecutableInstances using the ExecutableInstanceFactory and then calls their execute() method depending on how the model is defined.
My idea is to mock the ExecutableInstanceFactory class so that it returns mock ExecutableInstaces which I can then test for execution order. But this would mean that I have to inject the ExecutableInstanceFactory into the ExecutableInstance. Since it is a singleton, it would be dumb and stupid to pass it as a parameter. I thought of using Google's Guice for DI... but I'm stuck trying to do this.
Is my direction correct? If so, how should this be implemented?

I would make a few smaller methods out of this execute method. For example - one method for parsing which returns something to the execute method, then another one which does something with the returned data and returns other data etc. Then you would not have to test the Execute method, only the smaller ones. This will also allow you to detect bugs easier.

The execute method doesn't have input or output
So behaviour should be verified on the class' collaborators (use mocks).
Since it is a singleton, it would be dumb and stupid to pass it as a parameter.
The fact that you have problems testing shows you flaws in your design. Get rid of a singleton and inject the collaborators.

Related

Approach for enforcing a statement is present inside if condition through tests

I have a java project and I am looking for testing frameworks which allows me to enforce a constraint -
A specific method call on one object can only be called only after invoking another method on another object:
For example
if (validator.someMandatoryCheck()) {
myObject.performOperation();
}
I want to ensure that in my codebase, everywhere myObject.performOperation() is called, validator.someMandatoryCheck() has to be called first.
Is there a testing framework that would allow me to achieve this ?
To test your code snippet, you can use Mockito framework.
Mockito.when(validator.someMandatoryCheck()).thenReturns(true);
Mockito.verify(myObject).performOperation();
But myObject should be a mock object.
For more reference on verify method: http://www.baeldung.com/mockito-verify

Spring: scope linked to invocation method

I have a general question about Spring but which is a bit difficult to explain. So I will describe the situation I'm facing in order to make it easier to understand.
I have a simple #Singleton service that has a single method. I would like to use some helper classes to help me.
Every time the single method is called, I would like to be able to instantiate a new team of helper classes. As they need to work together, these classes need references to each other. But I don't want to construct them by myself. Once the method of the service returns, the helper instances can be GC.
Is it possible to use Spring to create a small team of helper classes all scoped to the call of the method in the #Singleton class ?

Anyway to create a Test Helper class that creates mocks?

In my testing of a legacy system, I have found myself having to mock similar classes for different parts of the system I'm increasing test coverage for. I would like to create a helper class for my tests that could call a method that would set up particular mocks and their return values.
Here's an example of a method I have had to create a few times in multiple tests.
public void mockClassINeedToMockToReturn(Boolean bool){
mockStatic(classINeedToMock.class);
when(classINeedToMock.getSuccess(Mockito.any(someClass.class))).thenReturn(bool);
}
I have tried setting this up in a HelperTest.class (in the same project/folder as my tests) and it isn't working. I have included both the following Annotations in the class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({classINeedToMock.class})
I have tried:
Using the methods statically and calling them in my tests. (does not mock)
Creating a HelperTest object and calling the method in my test. (still does not mock)
Having my tests Extend my HelperTest.class and calling the method from in my tests. (Still refuses to mock the class)
I'm sure this is something to do with the way the PowerMockRunner works. So is there a way to make this work? Or should I just come to terms with duplicating these methods throughout my project.
It's the little details.... When looking into it more I noticed the class I was mocking had 2 separate methods.
theClass.method(var1, var2);
theClass.method(var1, List<var2>);
One of my tests was calling the first method, the other was calling the second method. When I ran the second test (only having mocked the first method), it was calling the actual class because that method was not mocked.
After setting up the correct mock with the proper input parameters I could call the method statically and the mock would be created and used appropriately.

Easy mock behaviour while requested

I was thinking, is it possible to mock whole object behavior with EasyMock, but in a way that once declared mock with all expected values and results is used several times without caring about the order of the requests ?
The purpose for this is to create an instance of mock for example in JUnit test #BeforeClass and use it in several #Test methods.
Thank you in advance for any input,
Regards,
P.
If you are not interested in verifying calls to the mock, and your only aim is to ensure that whenever a specific method on the mock is called, it will always return the same desired result, you can configure it using andStubReturn(), e.g.
expect(mock.getMeaningOfLifeUniverseAndEverything()).andStubReturn(42);
I think you're really wanting two things:
The ability to use mocked methods out of order, which is the default easymock (non-strict mode),
The ability to use mocked methods any number of times.
You do the latter like this:
expect(someMock.someMethod()).anyTimes().andReturn(someValue);
If your method will get different arguments each time it is called, you can use the anyObject() method to ignore the provided argument.

How to mock object construction?

Is there a way to mock object construction using JMock in Java?
For example, if I have a method as such:
public Object createObject(String objectType) {
if(objectType.equals("Integer") {
return new Integer();
} else if (objectType.equals("String") {
return new String();
}
}
...is there a way to mock out the expectation of the object construction in a test method?
I'd like to be able to place expectations that certain constructors are being called, rather than having an extra bit of code to check the type (as it won't always be as convoluted and simple as my example).
So instead of:
assertTrue(a.createObject() instanceof Integer);
I could have an expectation of the certain constructor being called. Just to make it a bit cleaner, and express what is actually being tested in a more readable way.
Please excuse the simple example, the actual problem I'm working on is a bit more complicated, but having the expectation would simplify it.
For a bit more background:
I have a simple factory method, which creates wrapper objects. The objects being wrapped can require parameters which are difficult to obtain in a test class (it's pre-existing code), so it is difficult to construct them.
Perhaps closer to what I'm actually looking for is: is there a way to mock an entire class (using CGLib) in one fell swoop, without specifying every method to stub out?
So the mock is being wrapped in a constructor, so obviously methods can be called on it, is JMock capable of dynamically mocking out each method?
My guess is no, as that would be pretty complicated. But knowing I'm barking up the wrong tree is valuable too :-)
The only thing I can think of is to have the create method on at factory object, which you would than mock.
But in terms of mocking a constructor call, no. Mock objects presuppose the existence of the object, whereas a constructor presuppose that the object doesn't exist. At least in java where allocation and initialization happen together.
jmockit can do this.
See my answer in https://stackoverflow.com/questions/22697#93675
Alas, I think I'm guilty of asking the wrong question.
The simple factory I was trying to test looked something like:
public Wrapper wrapObject(Object toWrap) {
if(toWrap instanceof ClassA) {
return new Wrapper((ClassA) toWrap);
} else if (toWrap instanceof ClassB) {
return new Wrapper((ClassB) toWrap);
} // etc
else {
return null;
}
}
I was asking the question how to find if "new ClassAWrapper( )" was called because the object toWrap was hard to obtain in an isolated test. And the wrapper (if it can even be called that) is kind of weird as it uses the same class to wrap different objects, just uses different constructors[1]. I suspect that if I had asked the question a bit better, I would have quickly received the answer:
"You should mock Object toWrap to match the instances you're testing for in different test methods, and inspect the resulting Wrapper object to find the correct type is returned... and hope you're lucky enough that you don't have to mock out the world to create the different instances ;-)"
I now have an okay solution to the immediate problem, thanks!
[1] opening up the question of whether this should be refactored is well out of the scope of my current problem :-)
Are you familiar with Dependency Injection?
If no, then you ceartanly would benefit from learning about that concept. I guess the good-old Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler will serve as a good introduction.
With Dependency Injection (DI), you would have a DI container object, that is able to create all kinds of classes for you. Then your object would make use of the DI container to instanciate classes and you would mock the DI container to test that the class creates instances of expected classes.
Dependency Injection or Inversion of Control.
Alternatively, use the Abstract Factory design pattern for all the objects that you create. When you are in Unit Test mode, inject an Testing Factory which will tell you what are you creating, then include the assertion code in the Testing Factory to check the results (inversion of control).
To leave your code as clean as possible create an internal protected interface, implement the interface (your factory) with the production code as an internal class. Add a static variable type of your interface initialized to your default factory. Add static setter for the factory and you are done.
In your test code (must be in the same package, otherwise the internal interface must be public), create an anonymous or internal class with the assertion code and the test code. Then in your test, initialize the target class, assign (inject) the test factory, and run the methods of your target class.
I hope there is none.
Mocks are supposed to mock interfaces, which have no constructors... just methods.
Something seems to be amiss in your approach to testing here. Any reason why you need to test that explicit constructors are being called ?
Asserting the type of returned object seems okay for testing factory implementations. Treat createObject as a blackbox.. examine what it returns but dont micromanage how it does it. No one likes that :)
Update on the Update: Ouch! Desperate measures for desperate times eh? I'd be surprised if JMock allows that... as I said it works on interfaces.. not concrete types.
So
Either try and expend some effort on getting those pesky input objects 'instantiable' under the test harness. Go Bottom up in your approach.
If that is infeasible, manually test it out with breakpoints (I know it sucks). Then stick a "Touch it at your own risk" comment in a visible zone in the source file and move ahead. Fight another day.

Categories