Testing Google App Engine ThreadManager outside of GAE - java

I've written a JUnit (4.10) unit test that makes the following call to com.google.appengine.api.ThreadManager:
ThreadManager.currentRequestThreadFactory();
When this test runs, I get a NullPointerException being thrown from within this currentRequestThreadFactory method:
Caused by: java.lang.NullPointerException
at com.google.appengine.api.ThreadManager.currentRequestThreadFactory(ThreadManager.java:39)
at com.myapp.server.plumbing.di.BaseModule.providesThreadFactory(BaseModule.java:50)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
When I pull down the source for ThreadManager, and look at Line 39 (which is the source of the NPE), I see:
public static ThreadFactory currentRequestThreadFactory() {
return (ThreadFactory) ApiProxy.getCurrentEnvironment().getAttributes()
.get(REQUEST_THREAD_FACTORY_ATTR);
}
So it seems that the ApiProxy.getCurrentEnvironment() is null, and when it's getAttribute() method is called, the NPE is thrown. I've confirmed this by adding some new print statements higher up in my unit test code:
if(ApiProxy.getCurrentEnvironment() == null)
System.out.println("Environment is null.");
I'm vaguely aware that GAE offers "test versions" for all its services, but haven't been able to find (specifically) how to use them and set them up. So I ask: does GAE offer such test versions? If so, how do I add an ApiProxy test version here? And if not, then what are my options? I don't think I can mock either method (ThreadManager#currentRequestThreadFactory or ApiProxy#getCurrentEnvironment) because they're both statics. Thanks in advance.
Edit: I see that there is an appengine-testing.jar that ships with the SDK. Inside this JAR is an ApiProxyLocal.class that I believe is a version of ApiProxy that could be used during JUnit testing, that would work without throwing the NPE. If that's the case (which I'm not even sure of), then the question is: how do I inject it into my ThreadManager for this test?

You will get the correct Threads from the stubs, if you set up your LocalServiceTestHelper, along the following lines.
private static final LocalServiceTestHelper helper = new LocalServiceTestHelper( new LocalDatastoreServiceTestConfig());
#BeforeClass
public static void initialSetup() {
helper.setUp();
}
#AfterClass
public static void finalTearDown() {
helper.tearDown();
}

I suggest avoiding calling ThreadManager.currentRequestThreadFactory() directly from your code. Instead, inject the ThreadFactory into the class that needs to create threads.
One easy way to do this is with Guice:
public static class MyService {
private final ThreadFactory threadFactory;
#Inject
MyService(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
}
...
}
In your tests for MyService, you could either pass a fake ThreadFactoryto the MyService constructor or inject Executors.defaultThreadFactory().
In your production code, you would create a binding:
bind(ThreadFactory.class)
.toInstance(ThreadManager.currentRequestThreadFactory());
Of course, if you're not ready to jump into dependency injection, you can create your own accessors to get and set the ThreadFactory

If you're implementing ApiProxy.Environment as suggested in
http://code.google.com/appengine/docs/java/howto/unittesting.html
then the getAttributes() method is where you are not finding an
entry for REQUEST_THREAD_FACTORY_ATTR in your map.
You can add that:
attributes.put(REQUEST_THREAD_FACTORY_ATTR, new RequestThreadFactory());
For other helpful additions, see:
http://googleappengine.googlecode.com/svn-history/trunk/java/src/main/com/google/appengine/tools/development/LocalEnvironment.java

To add to the last answer, if you are starting a thread within your unit test case, that java thread needs the ApiProxy environment set too.
in your class LocalServiceTestCase extends TestCase, the setup method might look
something like this:
super.setUp();
helper1.setUp();
setEnvironment();
where:
public static void setEnvironment() {
if (ApiProxy.getCurrentEnvironment() == null) {
ApiProxyLocal apl = LocalServiceTestHelper.getApiProxyLocal();
ApiProxy.setEnvironmentForCurrentThread(new TEnvironment());
ApiProxy.setDelegate(apl);
}
}
The TEnvironment is given in the above urls.
You might want to make a static unsetEnvironment() too.
In your unit test case, if you've started a new java thread, you can just
use the static method at the beginning of your run method:
public void run() {
LocalServiceTestCase.setEnvironment();

Related

Equivalent to #DirtiesContext(...) for Surefire + JUnit?

I'm using the maven-surefire-plugin with junit 4.1.4. I have a unit test which relies on a 3rd party class that internally uses static { ... } code block to initiate some variables. For one test, I need to change one of these variables, but only for certain tests. I'd like this block to be re-executed between tests, since it picks up a value the first time it runs.
When testing, it seems like surefire instantiates the test class once, so the static { ... } code block is never processed again.
This means my unit tests that change values required for testing are ignored, the static class has already been instantiated.
💭 Note: The static class uses System.loadLibrary(...), from what I've found, it can't be rewritten to be instantiated, static is the (rare, but) proper usage.
I found a similar solution for Spring Framework which uses #DirtiesContext(...) annotation, allowing the programmer to mark classes or methods as "Dirty" so that a new class (or in many cases, the JVM) is initialized between tests.
How do you do the same thing as #DirtiesContext(...), but with maven-surefire-plugin?
public class MyTests {
#Test
public void test1() {
assertThat(MyClass.THE_VALUE, is("something-default"));
}
#Test
public void test2() {
System.setProperty("foo.bar", "something-else");
assertThat(MyClass.THE_VALUE, is("something-else"));
// ^-- this assert fails
// value still "something-default"
}
}
public class MyClass {
static {
String value;
if(System.getProperty("foo.bar") != null) {
value = System.getProperty("foo.bar"); // set to "something-else"
} else {
value = "something-default";
}
}
public static String THE_VALUE = value;
}
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>4.1.2</version>
</plugin>
static initialization blocks in java are something that can't be easily handled by JUnit. In general static stuff doesn't play nicely with unit testing concepts.
So, assuming you can't touch this code, your options are:
Option 1:
Spawn a new JVM for each test - well, this will work, but might be an overkill because it will aggravate the performance
If you'll follow this path, you might need to configure surefire plugin with:
forkCount=1
reuseForks=false
According to the surefire plugin documentation this combination will execute each test class in its own JVM process.
Option 2:
Create a class with a different class loader for every test.
Basically in Java if class com.foo.A is created by ClassLoader M is totally different than the same class com.foo.A created by ClassLoaded N.
This is somewhat hacky but should work.
The overhead is much smaller than in option 1. However you'll have to understand how to "incorporate" new class loaders into the testing infrastructure.
For more information about the creation of the custom class loader read for example this tutorial

How to write junit test for a class that has member variables that are topComponents?

public class Something {
private static Something something = new Something();
public static Something get(){
return something;
}
private EventQueueWindow eventQueue;
private Something(){
TopComponent tc = WindowManager.getDefault().findTopComponent("EventQueueWindow");
eventQueue = (EventQueueWindow) tc;
}
EventQueue getQueue(){
return eventQueue;
}
}//end class Something
Now I want to write a JUnit test which requires the ability to access eventQueue.
public void testgetQueue() {
Something something = Something.get();
assertEquals("Failed to return EventQueueWindow",something.getQueue().getClass(), EventQueueWindow.class);
}
I get a java.lang.NullPointerException when I run the test because eventQueue has a null value despite it being assigned a value in class Something's constructor. I've read around that this may have something to do with components being handle in a different thread or not being initialized before the test is run. But I'm pretty new to java and unit testing and don't know how to solve this problem. Any guidance would be appreciated.
Your biggest problem is that you have global state. Global state is generally poor programming, including with tests.
Testing for particular implementation class, probably isn't a very good test.
I suggest removing your global state and dependency upon the global state that you are lumbered with from your libraries, then test that.
I believe what is going on is that the class is designed to exist inside a large context. WindowManager gives the class access to that context but the context does not exist in the unit test therefore the manager returns null.
One solution is to have two overloads of the constructor with one taking the WindowManger as an argument. Then in the test pass a mocked WindowManager to this constructor.
Mocking example via Mockito:
WindowManager man = Mockito.mock(WindowManager.class);
EventQueueWindow window = Mockito.mock(EventQueueWindow.class);
Mockito.when(man.findTopComponent("EventQueueWindow")).thenReturn(window);

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;

mockito : how to unmock a method?

I have a JUnit class with different methods to perform different tests.
I use Mockito to create a spy on real instance, and then override some method which is not relevant to the actual test I perform.
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
say I have a spy object called 'wareHouseSpy'
say I overriden the method isSomethingMissing :
doReturn(false).when(wareHouseSpy).isSomethingMissing()
What will be the right way to un-override, and bring things back to normal on the spy i.e make the next invokation of isSomethingMissing to run the real method?
something like
doReturn(Mockito.RETURN_REAL_METHOD).when(wareHouseSpy).isSomethingSpy()
or maybe
Mockito.unmock(wareHouseSpy)
Who knows? I couldn't find nothing in that area
Thanks!
Assaf
I think
Mockito.reset(wareHouseSpy)
would do it.
Let's say most of your tests use the stubbed response. Then you would have a setUp() method that looks like this:
#Before
public void setUp() {
wareHouseSpy = spy(realWarehouse);
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
Now let's say you want to undo the stubbed response and use the real implementation in one test:
#Test
public void isSomethingMissing_useRealImplementation() {
// Setup
when(wareHouseSpy.isSomethingMissing()).thenCallRealMethod();
// Test - Uses real implementation
boolean result = wareHouseSpy.isSomethingMissing();
}
It depends whether you are testing with TestNG or JUnit.
JUnit creates a new instance of itself for each test method. You basically don't have to worry about reseting mocks.
With TestNG, you have to reset the mock(s) with Mockito.reset(mockA, mockB, ...) in either an #BeforeMethod or an #AfterMethod
The "normal" way is to re-instantiate things in your "setUp" method. However, if you have a real object that is expensive to construct for some reason, you could do something like this:
public class MyTests {
private static MyBigWarehouse realWarehouse = new MyBigWarehouse();
private MyBigWarehouse warehouseSpy;
#Before
public void setUp() {
warehouseSpy = spy(realWarehouse); // same real object - brand new spy!
doReturn(false).when(wareHouseSpy).isSomethingMissing();
}
#Test
...
#Test
...
#Test
...
}
Maybe I am not following but when you have a real object real:
Object mySpy = spy(real);
Then to "unspy" mySpy... just use real.
As per the documentation, we have
reset(mock);
//at this point the mock forgot any interactions & stubbing
The documentation specifies further
Normally, you don't need to reset your mocks, just create new mocks
for each test method. Instead of #reset() please consider writing
simple, small and focused test methods over lengthy, over-specified
tests.
Here's an example from their github repo which tests this behavior and uses it:
#Test
public void shouldRemoveAllInteractions() throws Exception {
mock.simpleMethod(1);
reset(mock);
verifyZeroInteractions(mock);
}
reference : ResetTest.java
Addressing this piece specifically:
Is there a way, just for the sake of cleaning up after me in case some other tests that run after my tests also use the same instances and might execute a mocked method they didn't ask to mock, to un-mock a method?
If you are using JUnit, the cleanest way to do this is to use #Before and #After (other frameworks have equivalents) and recreate the instance and the spy so that no test depends on or is impacted by whatever you have done on any other test. Then you can do the test-specific configuration of the spy/mock inside of each test. If for some reason you don't want to recreate the object, you can recreate the spy. Either way, everyone starts with a fresh spy each time.

How can I run different junit test based on the same (but changing) information/setup

I got a lot of different flows which are resuing moduls. Like this Flow1 = M1->M2->M3->M5 or Flow2 = M1->M2->M4->M6->M3->M5.
Now I want to write a testCase for each modul to shorten the time of testdevelopement and then combine those cases to test the flow. Those tests all need an initial setup, sometimes other paramters and certain informations should be carried through the flow. How can I insert them into the testmodul without hardcoding them into the model since they should be changeable for reuse.
Since testcases do not support constructors and parameterized test cases are not what I am looking for.
So not like
Running the same JUnit test case multiple time with different data
but Running differen JUnit test cases with the same source of data.
Is it possible to do that or am I on the wrong track?
If anything is unclear please ask.
I'd really appreciate help.
Greetings
Tarken
Let's see if I understand your problem correctly. You would like to define a test for M1 (testM1), a test for M2 (testM2) a test for M3 (testM3) etc. You would then like to test the combination of M1->M2->M3 by calling all of the test methods testM1, testM2, testM3 in order, but passing some arbitrary data between those methods. So testM1 gets called, and it produces some data which gets passed to testM2, which produces data which gets passed to testM3. The solution below is designed for this, but can easily be extended to include classes.
There are two ways of doing this. The easiest is to define a #Rule in your classes which gets the context stored in a static field in the Suite class and updates it. If you extend ExternalResource, you can do something like:
private Context context;
#Rule
public ExternalResource resource= new ExternalResource() {
#Override
protected void before() throws Throwable {
// get context from Suite class
context = MySuite.getContext();
};
#Override
protected void after() {
// put context into Suite class
MySuite.setContext(context);
};
};
Your methods would then use that context as normal. This would work in most cases, but creates a dependance from the test to a particular MySuite class.
The more complex option
You can do this using a custom #Suite class with a customer Runner. My answer to How to define JUnit method rule in a suite? shows how to execute custom code before and after a particular method (in that case one with a #depcrecated annotation).
You would need to do something similar. So your Suite would create the context for the test, and before executing a particular test method, the runner retrieves the context from the suite, calls a setter in the test class. The test method uses that context, returns and the runner retrieves the context from the test class and updates the suite class. The obvious place to store the context would be the suite, since the test classes themselves are created each time. I think it's too much work to try and pass the context in as a parameter, you'd have to change a lot more code.
So in your Runner, you would have something like
public class MyRunner extends BlockJUnit4ClassRunner {
private MySuite suite;
public MyRunner(Class<?> klass, MySuite suite) throws InitializationError {
super(klass);
this.suite = suite;
}
#Override
protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
Description description= describeChild(method);
if (method.getAnnotation(Ignore.class) != null) {
notifier.fireTestIgnored(description);
} else {
// call suite.getContext()
// call setContext() in class
runLeaf(methodBlock(method), description, notifier);
// call getContext() in class
// call suite.setContext()
}
}
}
It is possible to override the beforeclass behaviour as well.
Use BeforeClass.

Categories

Resources