Conditional generation of method bodies to satisfy large interfaces in Java - java

The Java OpenGL GL interface contains about 2000 methods, for debugging purposes I would like to wrap an instance and delegate calls to it while doing some logging. The logging code can be pushed to the same method in each case, so the task of writing out the method implementations looks like it could be automated. An example of what I am trying to do:
import javax.media.opengl.GL;
public class GLErrorLogger implements GL {
private final GL backing;
public GLErrorLogger(GL delegateToMe) {
backing = delegateToMe;
}
private void checkErrorCode() {
// Log frame and thread details depending on gl state
}
/**
* Example of a method
*/
#Override
public int glGenLists(int arg0) {
checkErrorCode();
int retVal = backing.glGenLists(arg0);
checkErrorCode();
return retVal;
}
// rest of methods here...
}
In other words copy the method name and parameters (minus their types) into a call on the backing object, surround with calls to the logging method, and if there is a return type then assign the result to a variable of this type and return it at the end of the method.
I looked at creating a one shot eclipse code template to autogenerate the methods, but there wasn't an immediately obvious way to do pattern matching on the return type. Can anyone suggest a way to do this in Eclipse or any of its code generation tools to save me pulling out the regex toolkit?

You might want to use an Aspect to create the necessary bytecode for you instead of producing all the source code. Take a look at the Traceing Aspect example here: Traceing Aspect Example.
As an Alternative, you can create a Java Dynamic Proxy, if you do not want to use AspectJ as Thrid party Library. Please refer to Dynamic Proxy Tutorial

Use JDK proxies as suggested, or: use a Mock Framework like EasyMock or Mockito.
GL mock = EasyMock.createMock(GL.class);
EasyMock.expect(mock.someMethod()).andReturn(someValue);
// or, if you need to do more computing:
EasyMock.expect(mock.someOtherMethod()).andAnswer(new IAnswer<String>() {
public String answer() throws Throwable {
return "some value you calculate here";
}
});
EasyMock.replay(mock);
now you can use the mock Object for all methods you configured.
See the EasyMock readme for more info.

Related

How to test a simple given method using Mockito

I am new to testing with java so it confuses me a little how to write a proper unit test to a method with no parameters and return value. In general the snippet looks like the below:
public class SplitterService {
private SentenceDAO sentenceObject;
private ObjectToXML objectToXML;
private ObjectToCSV objectToCSV;
public SplitterService(int selector, String inputPath, String outputPath) {
this(inputPath);
if (selector == 1)
objectToCSV = new ObjectToCSV(outputPath, size);
if (selector == 2)
objectToXML = new ObjectToXML(outputPath);
}
public void chooseConverter() {
if (objectToCSV != null)
objectToCSV.printRecord(sentenceObject);
if (objectToXML != null)
objectToXML.marshal(sentenceObject);
}
}
There are 3 private fields in the class. There is also a constructor which instantiate a given class. Then in the chooseConverter() method a proper action is taken according to the created object.
Could you please give me some advice how to test the chooseConverter method since there is no return value and a parameter (I know Junit 5 and a little of Mockito). Im not looking for any given solution just a few words how to approach my issue.
The code, in its current form, is not unit-test friendly.
As a last resort, you can test the side effects of ObjectToCSV and ObjectToXML, but lets try to do better than that.
Ideally, the class should provide some injection points to allow you inject new mock instances of ObjectToCSV and ObjectToXML.
There are multiple ways to introduce DI like providing factories for these objects in a constructor, extracting a factory of SplitterService which injects objectToCSV or objectToXML depending on the selector.
These methods require some modifications of the client code.
extracting methods that create instances of objectToCSV and objectToXML from the constructor requires a minimal code change and is transparent to the clients. In such case, you subclass your class and override builder methods to return mocks.
if no modifications to existing code are allowed, I can recommend pulling in Powermock and mocking the constructors. Note: you must be running junit4 vintage engine, as Powermock hasnt been ported to jUnit5 yet.
https://dzone.com/articles/using-powermock-mock
you are looking at a few things here... first check that objectToCSV::printRecord (objectToCSV will be a Mockito mock) is getting called under the condition objectToCSV != null (and objectToXML:: marshal is getting called under objectToXML != null). And also you are looking for ArgumentCaptor most probably, that is to test that objectToCSV::printRecord and objectToXML.marshal is actually getting called with sentenceObject that you set.

Junit testing method which returns nothing and has service call to other system

I have a method which does following.
public void callService(SomeObject someObject) {
// call helper class method and create a request XML
// scrub this XML using a local method and persist it in MongoDB
// call a 3rd party service using HTTP POST
// Recieve the response
// Persist the response in MongoDB and set in in somObject
// return
}
Now as part of development we have to write unit test cases for this method. I am new to Junit testing as well as mock objects. but when I googled and looked at the some other similar questions I understood that testing void method is little bit different than normal methods and I think my above method which special in some more way as I am clueless as to what and how to test for this method.
Can someone please give me pointer or any reference as to how I can unit test this method using Junit.
You'd probably want to use mocks to stand in for your Mongo connection and the third party service. It's easiest to use an existing mock framework, but this is the general concept.
Pretend that you post to this third party service by constructing a StuffToPost object and passing it to the post method on your ThirdPartyPoster. Then you can create a mock object as follows:
public class MockThirdPartyPoster implements ThirdPartyPoster {
private int count = 0;
private StuffToPost stuffToPost;
#Override
public void post(StuffToPost stuffToPost) {
this.count++;
this.stuffToPost = stuffToPost;
}
public int getCount() {
return count;
}
public StuffToPost getStuffToPost() {
return stuffToPost;
}
}
In your test, you'd construct this MockThirdPartyPoster and pass it to thingToTest.setThirdPartyPoster, then call your method. Once the method finishes executing, you can call getCount() on the mock to make sure that you POSTed once and only once, and call getStuffToPost() to examine the StuffToPost object and make sure that it is correct. You'd do something similar for Mongo persistence as well.
That calls for a lot of boilerplate; mock frameworks like Mockito or EasyMock exist to solve that problem.

how to use mockito spy for lazy evaluation?

I want to use mockito spy.
When I set a return value in both following ways:
when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate));
doReturn(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user, fakeNowDate)).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
I see the return value is being evaluated eagerly
meaning when this "setting" line is executed.
how can i force the spy to evaluate the return value only on demand?
meaning when the "when" condition is met.
update
Thanks to #RobbyCornelissen I have tried this code:
when(imagesSorterSpy.sortImages(imagesAsInsertionOrder, user)).thenAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
ImagesSorter mock = (ImagesSorter)invocation.getMock();
return mock.sortImages((List<Image>)args[0], (UserInfo)args[1], fakeNowDate);
}
});
But it didn't help:
1) the "when" expression was invoked immediately. (not wanted)
2) eventually the callback wasn't call.
First let me warn you on partial mocks, because that is what the code is actually doing, it's wrong design wise. It may be more relevant to use a strategy pattern to compose behavior of the tested subject. Mockito team (including me) strongly advises to stay away of partial mocks whenever possible.
EDIT : I don't know the code and I don't know exactly which component under test but from what I gather there's a type responsible to sort images, let's call it ImagesSorter.
So first case ImagesSorter is a dependency of a test subject, so in this case just stubbing the mock of ImagesSorter will do.
If however it is ImagesSorter itself under test, and stubbing a special method of this class is called a partial mock and it is plain wrong. It exposes internal of the production code in the test. So there's several solutions.
As the code snippet showed in the answer shows a fakeDate, one of the solution is to not use things like new Date() and code a simple class TimeSource whose sole responsibility is to provide a date. And in tests the bwhavior of this TimeSOurce could be overriden.
A simplier solution would be to use JodaTime as it provides this functionality built in.
If the scope of test goes beyond changing the date, then maybe ImagesSorter needs a way to be configured with other objects. Inspiration on how to do it can be found with the cache builder of guava. If the configuration is dead simple then a simple constructor coud do it.
That could look like :
class ImagesSorter {
ImagesSorterAlso algo;
ImagesSorter(ImagesSorterAlgo algo) { this.algo = algo; }
Iterable sortImages(...) {
algo.sort(...);
}
}
interface ImagesSorterAlgo {
Iterable sort(...);
}
Now about your questions :
1) the "when" expression was invoked immediately. (not wanted)
It is expected imagesSorterSpy is a spy so by default it calls the real code. Instead you should use the alternate API, the same that #RobbyCornelissen showed. i.e.
doAnswer(sortWithFakeDate()).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
// with BDD aliases (BDDMockito) which I personnaly finds better
willAnswer(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
will(sortWithFakeDate()).given(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);
sortWithFakeDate() would a static factory method that returns the answer, so the code reads well, and maybe reused elsewhere.
2) eventually the callback wasn't call.
This issue is most probably due to non equal arguments. You may need to check the equals method. Or relax the stub using the any() matcher.
I don't know the types of the arguments and classes you're using, so I can't provide a complete example, but you can stub using callbacks with the Answer<T> interface:
Mockito.doAnswer(new Answer() {
Object answer(InvocationOnMock invocation) {
ImagesSorter mock = (ImagesSorter) invocation.getMock();
Object[] args = invocation.getArguments();
return mock.sortImages((List<Image>) args[0], (UserInfo) args[1],
fakeNowDate);
}
}).when(imagesSorterSpy).sortImages(imagesAsInsertionOrder, user);

Clarification in Java Code Testing

I have started reading the Spring in Action book.
I have no knowledge of JUnit which I think my doubt is about.
There is a code fragment where the author refers to and says that it is difficult to test:
package com.springinaction.knights;
public classDamselRescuingKnight implements Knight {
private RescueDamselQuest quest;
public DamselRescuingKnight() {
quest = new RescueDamselQuest();
}
public voidembarkOnQuest() throwsQuestException {
quest.embark();
}
}
The author says that:
It’d be terribly difficult to write a unit test for DamselRescuingKnight. In such a test, you’d like to be able to assert that the quest’s embark() method is called when the knight’s embarkOnQuest() is called. But there’s no clear way to accomplish that here. Unfortunately, DamselRescuingKnight will remain untested.
What does the author mean by this?
Why is the code difficult to test here?
My initial thought is that it is difficult to test because the "RescureDamselQuest" object is initialized in the constructor. This makes it difficult to for example insert a mock object. A mock object would help you test that the embark() method is called on the "RescueDamselQuest" object.
A better way to solve this can be to either include a parameter in the constructor (usually I prefer this method):
public DamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
Or add a setter:
public void setDamselRescuingKnight(RescueDamselQuest quest){
this.quest = quest;
}
A common example I give is consider that you want to open a file, parse it, and get a data class out. Most will do something like:
Data openAndParse(String filename) {
...openFile
...parse
}
By doing it this way, the file open methodology and parse is highly coupled and difficult to test. If you have a problem in open and parse is it with the parse or the open?
By writing JUnit test, you are forced, for simplicity sake, to do something like...
BufferedReader openFile(String filename) {
...open file and return reader
}
Data parse(BufferedReader input) {
...parse and return data
}
JUnit leads us to a more cohesive solution. We write JUnit test simply by creating a string, constructing a StringReader, and then a BufferedReader. Well guess what? Very similarly we can now use parse to accept input from a variety of sources not just the file.
It's difficult to test because the quest implementation cannot be swapped out. Without byte code modification there's no trivial way to see if embark is called.
If you could set the quest implementation in a constructor or setter you could pass in an implementation that can spy on the call to embark.
One need to increase accessibility of fields and method of class to test. For example if one is testing a method which is package-private (default) then test cases which are generally in different package will not able to test this method. Therefore it is advised to to change in accessibility of fields to test the method. DamselRescuingKnight class can be tested which is not using DI by modifying the accessibility of RescueDamselQuest field from private to default. Then writing test case using mockito. Here is code for test case
#Test
public void knightShouldEmbarkOnQuest() throws QuestException {
DamselRescuingKnight knight = new DamselRescuingKnight();
RescueDamselQuest quest = mock(RescueDamselQuest.class);
knight.quest = quest;
knight.embarkOnQuest();
verify(quest, times(1)).embark();
}
And line which was changed in DamselRescuingKnight class to remove private accessibility
RescueDamselQuest quest;

log all the attribute changes of a Class

For debugging purposes I need to keep track of a Class attributes changes.
For example consider the following class:
class Test {
int myInt;
String myString;
...
public void setMyInt(int a) ...
public void setMyString(String s) ...
public printDebugLog();
}
void main() {
Test t = new Test();
t.setMyInt(5);
t.setMyString("Hello");
t.printDebugLog();
}
I want to output to be something like:
myInt => 5
myString => Hello
The easy solution is to create logs instantly. i.e. adding a Log function as follow:
void Log(String s) {
System.out.println(s);
}
and then code the set functions like below:
void setMyString(String s) {
myString = s;
Log("myString => " + s);
}
this requires all the set functions to be written variously and I wonder if there are any better solution for such matter. For example it might be easier (if possible) to create a SetValue function which accepts two variables and set the first attribute to the value of the second object. or something like this.
Any idea?
To do this you should wrap your class with orthogonal code that performs logging.
Since your class does not implement interface you cannot use dynamic proxy, so you have to use one of solutions that use byte code engineering.
The strongest solution I know is AspectJ. But probably you even do not need it. You can use Javassist or CGLIb - the byte code engineering libraries that allow creating proxies that wrap classes, so you can add code that performs logging.
You can use AOP to intercept the setter methods and log when they are called. A quick google should give you a few examples.
If you debug via JPDA,
you can create a Breakpoint
on a field you like to watch.

Categories

Resources