Check number of invocations within class in case of JUnit testing - java

I have a code which calculates something, caches is, and if already calculated, then reads from the cache; similar to this:
public class LengthWithCache {
private java.util.Map<String, Integer> lengthPlusOneCache = new java.util.HashMap<String, Integer>();
public int getLenghtPlusOne(String string) {
Integer cachedStringLenghtPlusOne = lengthPlusOneCache.get(string);
if (cachedStringLenghtPlusOne != null) {
return cachedStringLenghtPlusOne;
}
int stringLenghtPlusOne = determineLengthPlusOne(string);
lengthPlusOneCache.put(string, new Integer(stringLenghtPlusOne));
return stringLenghtPlusOne;
}
protected int determineLengthPlusOne(String string) {
return string.length() + 1;
}
}
I want to test if function determineLengthPlusOne has been called adequate number of times, like this:
public class LengthWithCacheTest {
#Test
public void testGetLenghtPlusOne() {
LengthWithCache lengthWithCache = new LengthWithCache();
assertEquals(6, lengthWithCache.getLenghtPlusOne("apple"));
// here check that determineLengthPlusOne has been called once
assertEquals(6, lengthWithCache.getLenghtPlusOne("apple"));
// here check that determineLengthPlusOne has not been called
}
}
Mocking class LengthWithCache does not seem a good option, as I want to test their functions. (According to my understanding we mock the classes used by the tested class, and not the tested class itself.) Which is the most elegant solution for this?
My first idea was to create another class LengthPlusOneDeterminer containing function determineLengthPlusOne, add pass it to function getLenghtPlusOne as parameter, and mock LengthPlusOneDeterminer in case of unit testing, but that seems a bit strange, as it has unnecessary impact on the working code (the real clients of class LengthWithCache).
Basically I am using Mockito, but whatever mock framework (or other solution) is welcome! Thank you!

Most elegant way would be to create a separate class that does the caching and decorate with it the current class (after removal of the caching), this way you can safely unit test the caching itself without interfering with functionalities of the base class.
public class Length {
public int getLenghtPlusOne(String string) {
int stringLenghtPlusOne = determineLengthPlusOne(string);
lengthPlusOneCache.put(string, new Integer(stringLenghtPlusOne));
return stringLenghtPlusOne;
}
protected int determineLengthPlusOne(String string) {
return string.length() + 1;
}
}
public class CachedLength extends Length {
private java.util.Map<String, Integer> lengthPlusOneCache = new java.util.HashMap<String, Integer>();
public CachedLength(Length length) {
this.length = length;
}
public int getLenghtPlusOne(String string) {
Integer cachedStringLenghtPlusOne = lengthPlusOneCache.get(string);
if (cachedStringLenghtPlusOne != null) {
return cachedStringLenghtPlusOne;
}
return length.getLenghtPlusOne(string);
}
}
Then you can easily test the caching my injecting a mocked Length:
Length length = Mockito.mock(Length.class);
CachedLength cached = new CachedLength(length);
....
Mockito.verify(length, Mockito.times(5)).getLenghtPlusOne(Mockito.anyInt());

You don't need mock to address your need.
To test the internal behavior (is getLenghtPlusOne() was called or not called), you would need to have a method to access to the cache in LengthWithCache.
But at level of your design, we imagine that you don't want to open the cache in a public method. Which is normal.
Multiple solutions exist to do a test on the cache behavior despite this constraint.
I will present my way of doing. Maybe, there is better.
But I think that in most of cases, you will be forced to use some tricks or to complexify your design to do your unit test.
It relies on augmenting your class to test by extending it in order to add the needed information and behavior for your test.
And it's this subclass you will use in your unit test.
The most important point in this class extension is not to break or modify the behavior of the object to test.
It must add new information and add new behavior and not modify information and behavior of the original class otherwise the test loses its value since it doesn't test any longer the behavior in the original class.
The key points :
- having a private field lengthPlusOneWasCalledForCurrentCallwhich registers for the current call if the method lengthPlusOneWasCalledwas called
- having a public method to know the value of lengthPlusOneWasCalledForCurrentCall for the string used as parameter. It enable the assertion.
- having a public method to clean the state of lengthPlusOneWasCalledForCurrentCall. It enable to keep a clean state after the assertion.
package cache;
import java.util.HashSet;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
public class LengthWithCacheTest {
private class LengthWithCacheAugmentedForTest extends LengthWithCache {
private Set<String> lengthPlusOneWasCalledForCurrentCall = new HashSet<>();
#Override
protected int determineLengthPlusOne(String string) {
// start : info for testing
this.lengthPlusOneWasCalledForCurrentCall.add(string);
// end : info for testing
return super.determineLengthPlusOne(string);
}
// method for assertion
public boolean isLengthPlusOneCalled(String string) {
return lengthPlusOneWasCalledForCurrentCall.contains(string);
}
// method added for clean the state of current calls
public void cleanCurrentCalls() {
lengthPlusOneWasCalledForCurrentCall.clear();
}
}
#Test
public void testGetLenghtPlusOne() {
LengthWithCacheAugmentedForTest lengthWithCache = new LengthWithCacheAugmentedForTest();
final String string = "apple";
// here check that determineLengthPlusOne has been called once
Assert.assertEquals(6, lengthWithCache.getLenghtPlusOne(string));
Assert.assertTrue(lengthWithCache.isLengthPlusOneCalled(string));
// clean call registered
lengthWithCache.cleanCurrentCalls();
// here check that determineLengthPlusOne has not been called
Assert.assertEquals(6, lengthWithCache.getLenghtPlusOne(string));
Assert.assertFalse(lengthWithCache.isLengthPlusOneCalled(string));
}
}
Edit 28-07-16 to show why more code is needed to handle more scenarios
Suppose, i will improve the test by asserting that there is no side effects : adding an element in the cache for a key has not effect on how the cache is handled for other keys.
This test fails because it doesn't rely on the string key. So, it always increments.
#Test
public void verifyInvocationCountsWithDifferentElementsAdded() {
final AtomicInteger plusOneInvkCounter = new AtomicInteger();
LengthWithCache lengthWithCache = new LengthWithCache() {
#Override
protected int determineLengthPlusOne(String string) {
plusOneInvkCounter.incrementAndGet();
return super.determineLengthPlusOne(string);
}
};
Assert.assertEquals(0, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne("apple");
Assert.assertEquals(1, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne("pie");
Assert.assertEquals(1, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne("eggs");
Assert.assertEquals(1, plusOneInvkCounter.get());
}
My version is longer because it provides more features and so, it can handle a broader range of unit testing scenarios .
Edit 28-07-16 to point the Integer caching
No direct relation with the original question but little wink :)
Your getLenghtPlusOne(String string) should use Integer.valueOf(int) instead of new Integer(int)
Integer.valueOf(int) uses in internal a cache

It feels like using mocks is overthinking it. The LengthWithCache can be overridden as an anonymous-inner class within the context of a test to get the invocation count. This requires no restructuring of the existing class being tested.
public class LengthWithCacheTest {
#Test
public void verifyLengthEval() {
LengthWithCache lengthWithCache = new LengthWithCache();
assertEquals(6, lengthWithCache.getLenghtPlusOne("apple"));
}
#Test
public void verifyInvocationCounts() {
final AtomicInteger plusOneInvkCounter = new AtomicInteger();
LengthWithCache lengthWithCache = new LengthWithCache() {
#Override
protected int determineLengthPlusOne(String string) {
plusOneInvkCounter.incrementAndGet();
return super.determineLengthPlusOne(string);
}
};
lengthWithCache.getLenghtPlusOne("apple");
assertEquals(1, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne("apple");
lengthWithCache.getLenghtPlusOne("apple");
lengthWithCache.getLenghtPlusOne("apple");
lengthWithCache.getLenghtPlusOne("apple");
lengthWithCache.getLenghtPlusOne("apple");
lengthWithCache.getLenghtPlusOne("apple");
assertEquals(1, plusOneInvkCounter.get());
}
}
It's worth noting the separation between the two tests. One verifies
that the length eval is right, the other verifies the invocation
count.
If a wider data set for validation is required, then you can turn the Test above into a Parameterized test and provide multiple data sets and expectations. In the sample below I've added a data set of 50 strings (lengths 1-50), an empty string, and a null value.
Null fails
#RunWith(Parameterized.class)
public class LengthWithCacheTest {
#Parameters(name="{0}")
public static Collection<Object[]> buildTests() {
Collection<Object[]> paramRefs = new ArrayList<Object[]>();
paramRefs.add(new Object[]{null, 0});
paramRefs.add(new Object[]{"", 1});
for (int counter = 1 ; counter < 50; counter++) {
String data = "";
for (int index = 0 ; index < counter ; index++){
data += "a";
}
paramRefs.add(new Object[]{data, counter+1});
}
return paramRefs;
}
private String stringToTest;
private int expectedLength;
public LengthWithCacheTest(String string, int length) {
this.stringToTest = string;
this.expectedLength = length;
}
#Test
public void verifyLengthEval() {
LengthWithCache lengthWithCache = new LengthWithCache();
assertEquals(expectedLength, lengthWithCache.getLenghtPlusOne(stringToTest));
}
#Test
public void verifyInvocationCounts() {
final AtomicInteger plusOneInvkCounter = new AtomicInteger();
LengthWithCache lengthWithCache = new LengthWithCache() {
#Override
protected int determineLengthPlusOne(String string) {
plusOneInvkCounter.incrementAndGet();
return super.determineLengthPlusOne(string);
}
};
assertEquals(0, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne(stringToTest);
assertEquals(1, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne(stringToTest);
assertEquals(1, plusOneInvkCounter.get());
lengthWithCache.getLenghtPlusOne(stringToTest);
assertEquals(1, plusOneInvkCounter.get());
}
}
Parameterized testing is one of the best ways to vary your data set through a test, but it adds complexity to the test and can be difficult to maintain. It's useful to know about, but not always the right tool for the job.

As this was an interesting question, I decided to write the tests. In two different ways, one with mocking and the other without. (Personally, I prefer the version without mocking.) In either case, the original class is tested, with no modifications:
package example;
import mockit.*;
import org.junit.*;
import static org.junit.Assert.*;
public class LengthWithCacheMockedTest {
#Tested(availableDuringSetup = true) #Mocked LengthWithCache lengthWithCache;
#Before
public void recordComputedLengthPlusOneWhileFixingTheNumberOfAllowedInvocations() {
new Expectations() {{
lengthWithCache.determineLengthPlusOne(anyString); result = 6; times = 1;
}};
}
#Test
public void getLenghtPlusOneNotFromCacheWhenCalledTheFirstTime() {
int length = lengthWithCache.getLenghtPlusOne("apple");
assertEquals(6, length);
}
#Test
public void getLenghtPlusOneFromCacheWhenCalledAfterFirstTime() {
int length1 = lengthWithCache.getLenghtPlusOne("apple");
int length2 = lengthWithCache.getLenghtPlusOne("apple");
assertEquals(6, length1);
assertEquals(length1, length2);
}
}
package example;
import mockit.*;
import org.junit.*;
import static org.junit.Assert.*;
public class LengthWithCacheNotMockedTest {
#Tested LengthWithCache lengthWithCache;
#Test
public void getLenghtPlusOneNotFromCacheWhenCalledTheFirstTime() {
long t0 = System.currentTimeMillis(); // millisecond precision is enough here
int length = lengthWithCache.getLenghtPlusOne("apple");
long dt = System.currentTimeMillis() - t0;
assertEquals(6, length);
assertTrue(dt >= 100); // assume at least 100 millis to compute the expensive value
}
#Test
public void getLenghtPlusOneFromCacheWhenCalledAfterFirstTime() {
// First time: takes some time to compute.
int length1 = lengthWithCache.getLenghtPlusOne("apple");
// Second time: gets from cache, takes no time.
long t0 = System.nanoTime(); // max precision here
int length2 = lengthWithCache.getLenghtPlusOne("apple");
long dt = System.nanoTime() - t0;
assertEquals(6, length1);
assertEquals(length1, length2);
assertTrue(dt < 1000000); // 1000000 nanos = 1 millis
}
}
Just one detail: for the tests above to work, I added the following line inside the LengthWithCache#determineLengthPlusOne(String) method, in order to simulate the real-world scenario where the computation takes some time:
try { Thread.sleep(100); } catch (InterruptedException ignore) {}

Based on the proposal by krzyk here is my fully working solution:
The calculator itself:
public class LengthPlusOneCalculator {
public int calculateLengthPlusOne(String string) {
return string.length() + 1;
}
}
The separate caching mechanism:
public class LengthPlusOneCache {
private LengthPlusOneCalculator lengthPlusOneCalculator;
private java.util.Map<String, Integer> lengthPlusOneCache = new java.util.HashMap<String, Integer>();
public LengthPlusOneCache(LengthPlusOneCalculator lengthPlusOneCalculator) {
this.lengthPlusOneCalculator = lengthPlusOneCalculator;
}
public int calculateLenghtPlusOne(String string) {
Integer cachedStringLenghtPlusOne = lengthPlusOneCache.get(string);
if (cachedStringLenghtPlusOne != null) {
return cachedStringLenghtPlusOne;
}
int stringLenghtPlusOne = lengthPlusOneCalculator.calculateLengthPlusOne(string);
lengthPlusOneCache.put(string, new Integer(stringLenghtPlusOne));
return stringLenghtPlusOne;
}
}
The unit test for checking the LengthPlusOneCalculator:
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class LengthPlusOneCalculatorTest {
#Test
public void testCalculateLengthPlusOne() {
LengthPlusOneCalculator lengthPlusOneCalculator = new LengthPlusOneCalculator();
assertEquals(6, lengthPlusOneCalculator.calculateLengthPlusOne("apple"));
}
}
And finally, the unit test for LengthPlusOneCache, checking the number of invocations:
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import org.junit.Test;
public class LengthPlusOneCacheTest {
#Test
public void testNumberOfInvocations() {
LengthPlusOneCalculator lengthPlusOneCalculatorMock = mock(LengthPlusOneCalculator.class);
when(lengthPlusOneCalculatorMock.calculateLengthPlusOne("apple")).thenReturn(6);
LengthPlusOneCache lengthPlusOneCache = new LengthPlusOneCache(lengthPlusOneCalculatorMock);
verify(lengthPlusOneCalculatorMock, times(0)).calculateLengthPlusOne("apple"); // verify that not called yet
assertEquals(6, lengthPlusOneCache.calculateLenghtPlusOne("apple"));
verify(lengthPlusOneCalculatorMock, times(1)).calculateLengthPlusOne("apple"); // verify that already called once
assertEquals(6, lengthPlusOneCache.calculateLenghtPlusOne("apple"));
verify(lengthPlusOneCalculatorMock, times(1)).calculateLengthPlusOne("apple"); // verify that not called again
}
}
We can safely do the mocking mechanism, as we are already convinced that the mocked class works properly, using its own unit tests.
Normally this is built into a build system; this example can be complied and run from command line as follows (files junit-4.10.jar and mockito-all-1.9.5.jar have to be copied to the working directory):
javac -cp .;junit-4.10.jar;mockito-all-1.9.5.jar *.java
java -cp .;junit-4.10.jar org.junit.runner.JUnitCore LengthPlusOneCalculatorTest
java -cp .;junit-4.10.jar;mockito-all-1.9.5.jar org.junit.runner.JUnitCore LengthPlusOneCacheTest
However, I'm still not fully satisfied with this approach. My issues are the following:
Function calculateLengthPlusOne is mocked. I would prefer such a solution where a mocking or whatever framework just calculates the number of invocations, but the original code runs. (Somehow mentioned by davidhxxx, however I do not find also that a perfect one.)
The code became a bit over-complicated. This is not the way one would create normally. Therefore this approach is not adequate if the original code is not of our fully control. This could be a constraint in reality.
Normally I would make function calculateLengthPlusOne static. This approach does not work in such a case. (But maybe my Mockito knowledge is weak.)
If some could address any of these issues, I would really appreciate it!

Related

JUnit testing / calling function few times

I am extracting concept from a single page and that page is being used in different functions, so i have created a function that assigns the value if value hasn't been assigned yet.
public String text() {
if (text.isPresent()) {
return text.get();
}
this.text = Optional.of(extractText(pdDocument));
return text.get();
}
I would like to create a test that checks that the function is being called once and the context is shared between the functions that doing some functionality in the same context
Here is an example when text() is being called twice
private Optional<String> packingListNet() {
return locatePattern(text(), PACKING_LIST_NET);
}
private Optional<String> packingListNumber() {
return locatePattern(text(), PACKING_LIST_NUMBER);
}
Would be grateful for any information, thank you
The technical answer: you could use a mocking library, such as PowerMockito, to create mocked instances of the Optional class. And when you have a mock object, you can instruct the mock how to react to method calls. Then you need to "get" the mocked Optional object into your class under test.
You could use that to cover the first if statement: you expect the mock to see the isPresent() call, to return true, and to then return a specific string. Your testcase could then check "that expected string came back". Similar for the other way round, when the mocked Optional "is empty", then you ensure another string is returned, and you check for that.
But honestly, it is doubtful if you should do that all.
You should focus on the public contract that your method there provides.
And that would mean:
Enable yourself that you can pass in a (real) Optional object into the class under test
When your Optional is not empty, your test expects ... what you put into it
When your Optional is empty, your test expects whatever extractText() will return
Of course, mocking is really problematic here: Optional is a final class. So you need to either use Mockito with "experimental support for final enabled", or you need to use PowerMock(ito) (which I strongly advise to never use).
So, as said: avoid mocking.
I think this method is badly conceived. It may rely on private, mutable state that will be a problem with multiple documents and threads accessing them.
A better approach would be to pass all the necessary information as method parameters. They are thread safe that way;
public static String getText(String textToSearchFor, Document pdfDocument) {
// extract here
}
Here's how I might write a JUnit test for a method like this:
public class TextMethodOwnerTest {
#Test
public void testGetText_Success() {
// setup
String expected = "text to find";
Document pdf; // Have to get this.
// exercise
String actual = TextMethodOwner.getText(expected, pdf);
// assert
Assert.assertEquals(expected, actual);
}
#Test
public void testGetText_PackingListNumber() {
// Add another case here
}
#Test
public void testGetText_PackingListNet() {
// Add another case here
}
}
I am not sure what are you trying to ask. Information is not clear but maybe this can help you:
Junit and mockito are mostly used togther. If you want to check any function gets called only one time we use verify() method of mockito with parameter atLeast(1)
For example: Example taken from (https://www.baeldung.com/mockito-verify)
List<String> mockedList = mock(MyList.class);
mockedList.clear();
mockedList.clear();
mockedList.clear();
verify(mockedList, atLeast(1)).clear();
Here is some pseudo code how you could achieve it:
public Class {
int counter = 0;
void test() {
counter++;
}
}
public ClassTest {
public Class class;
void shouldBeCalledOneTime() {
class.test();
AssertThat(class).hasFieldWithValue("counter", 1);
}
}
Since your question seemed to me mostly about reading the file only once, which is quite a genuine need for many, I wrote up this class using your code, but without JUnit.
This has a main method that calls the packingList*() method 100 times to different threads, but you will see that the extraction part is entered into only once in the beginning. For this, I have added a lock and used a synchronized block. I understand that this is basic, but thought I may share since it might help others.
Note the changes in the method public String text().
public class ReusedText{
private static final long PACKING_LIST_NET = 200;
private static final long PACKING_LIST_NUMBER = 120;
private Optional<String> text = Optional.ofNullable( null );
private Document pdDocument;
private static final Object LOCK = new Object();
private static final ExecutorService svc = Executors.newFixedThreadPool( 2 );
public ReusedText(Document pdDocument) {
super();
this.pdDocument = pdDocument;
}
public static void main( String[] args ){
ReusedText rt = new ReusedText( new Document( "/path/to/document/on/disk" ) );
for( int i = 0; i < 100; i++ ) {
svc.submit( () -> System.out.println( rt.packingListNet() ) );
svc.submit( () -> System.out.println( rt.packingListNumber() ) );
}
svc.shutdown();
}
public String text() {
if (text.isPresent()) {
return text.get();
}
else {
synchronized (LOCK) {
/* This repeated 'if' block is necessary because 'text' may have got populated while this thread was waiting for lock. */
if (text.isPresent()) return text.get();
else{
System.out.println( "Extracting text..." );
this.text = Optional.of( extractText( pdDocument ) );
return text.get();
}
}
}
}
private String extractText( Document doc ) {
//Read the file contents using some API like java.nio.file.Files or Apache Tika
return "file contents here!";
}
private Optional<String> packingListNet() {
return locatePattern(text(), PACKING_LIST_NET);
}
private Optional<String> packingListNumber() {
return locatePattern(text(), PACKING_LIST_NUMBER);
}
private Optional<String> locatePattern( String text, long packingListNumber ){
//Implement your logic with the text here.
return Optional.of( String.valueOf( packingListNumber ) );
}
private static class Document{
private String pathToText;
public Document(String pathToText) {
super();
this.pathToText = pathToText;
}
public String getPathToText(){
return pathToText;
}
}
}

Java synchronization depending on method parameter

how can I provide synchronization upon method parameter values?
All method calls using the 'same' parameter value A should be synchronized. A method call with a different parameter value e.g. B can access, even when calls with A are already waiting. The next concurrent call for B must wait also for the first B to be released.
My use case: I want to synchronize the access to JPA entities on ID level but want to avoid pessimistic locking because I need kind of a queue. The 'key' for locking is intended to be the entity ID - which is in fact of the type Java Long.
protected void entityLockedAccess(SomeEntity myEntity) {
//getId() returns different Long objects so the lock does not work
synchronized (myEntity.getId()) {
//the critical section ...
}
}
I read about lock objects but I am not sure how they would suit in my case.
On the top level I want to manage a specific REST call to my application which executes critical code.
Thanks,
Chris
As far as I understood you basically want a different, unique lock for each of your SomeEntity IDs.
You could realize this with a Map<Integer, Object>.
You simply map each ID to an object. Should there already be an object, you reuse it. This could look something like this:
static Map<Integer, Object> locks = new ConcurrentHashMap<>();
public static void main(String[] args)
{
int i1 = 1;
int i2 = 2;
foo(i1);
foo(i1);
foo(i2);
}
public static void foo(int o)
{
synchronized (locks.computeIfAbsent(o, k -> new Object()))
{
// computation
}
}
This will create 2 lock objects in the map as the object for i1 is reused in the second foo(i1) call.
Objects which are pooled and potentially reused should not be used for synchronization. If they are, it can cause unrelated threads to deadlock with unhelpful stacktraces.
Specifically, String literals, and boxed primitives such as Integers should NOT be used as lock objects because they are pooled and reused.
The story is even worse for Boolean objects because there are only two instances of Boolean, Boolean.TRUE and Boolean.FALSE and every class that uses a Boolean will be referring to one of the two.
I read about lock objects but I am not sure how they would suit in my
case. On the top level I want to manage a specific REST call to my
application which executes critical code.
You DB will take care for concurrent writes and other transactional issues.
All you need to do is use Transactions.
I would also recommend you to go through the classical problems (DIRTY READs NON Repeatable reads). You can also use Optimistic Locking for
The problem is that you simply should not synchronize on values (for example strings, or Integer objects).
Meaning: you would need to define some special EntityId class here, and of course, all "data" that uses the same ID would somehow need to be using the same EntityId object then.
private static final Set<Integer> lockedIds = new HashSet<>();
private void lock(Integer id) throws InterruptedException {
synchronized (lockedIds) {
while (!lockedIds.add(id)) {
lockedIds.wait();
}
}
}
private void unlock(Integer id) {
synchronized (lockedIds) {
lockedIds.remove(id);
lockedIds.notifyAll();
}
}
public void entityLockedAccess(SomeEntity myEntity) throws InterruptedException {
try {
lock(myEntity.getId());
//Put your code here.
//For different ids it is executed in parallel.
//For equal ids it is executed synchronously.
} finally {
unlock(myEntity.getId());
}
}
id can be not only an 'Integer' but any class with correctly overridden 'equals' and 'hashCode' methods.
try-finally - is very important - you must guarantee to unlock waiting threads after your operation even if your operation threw exception.
It will not work if your back-end is distributed across multiple servers/JVMs.
Just use this class:
(and the map will NOT increase in size over time)
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
public class SameKeySynchronizer<T> {
private final ConcurrentHashMap<T, Object> sameKeyTasks = new ConcurrentHashMap<>();
public void serializeSameKeys(T key, Consumer<T> keyConsumer) {
// This map will never be filled (because function returns null), it is only used for synchronization purposes for the same key
sameKeyTasks.computeIfAbsent(key, inputArgumentKey -> acceptReturningNull(inputArgumentKey, keyConsumer));
}
private Object acceptReturningNull(T inputArgumentKey, Consumer<T> keyConsumer) {
keyConsumer.accept(inputArgumentKey);
return null;
}
}
Like in this test:
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class SameKeySynchronizerTest {
private static final boolean SHOW_FAILING_TEST = false;
#Test
void sameKeysAreNotExecutedParallel() throws InterruptedException {
TestService testService = new TestService();
TestServiceThread testServiceThread1 = new TestServiceThread(testService, "a");
TestServiceThread testServiceThread2 = new TestServiceThread(testService, "a");
testServiceThread1.start();
testServiceThread2.start();
testServiceThread1.join();
testServiceThread2.join();
Assertions.assertFalse(testService.sameKeyInProgressSimultaneously);
}
#Test
void differentKeysAreExecutedParallel() throws InterruptedException {
TestService testService = new TestService();
TestServiceThread testServiceThread1 = new TestServiceThread(testService, "a");
TestServiceThread testServiceThread2 = new TestServiceThread(testService, "b");
testServiceThread1.start();
testServiceThread2.start();
testServiceThread1.join();
testServiceThread2.join();
Assertions.assertFalse(testService.sameKeyInProgressSimultaneously);
Assertions.assertTrue(testService.differentKeysInProgressSimultaneously);
}
private class TestServiceThread extends Thread {
TestService testService;
String key;
TestServiceThread(TestService testService, String key) {
this.testService = testService;
this.key = key;
}
#Override
public void run() {
testService.process(key);
}
}
private class TestService {
private final SameKeySynchronizer<String> sameKeySynchronizer = new SameKeySynchronizer<>();
private Set<String> keysInProgress = ConcurrentHashMap.newKeySet();
private boolean sameKeyInProgressSimultaneously = false;
private boolean differentKeysInProgressSimultaneously = false;
void process(String key) {
if (SHOW_FAILING_TEST) {
processInternal(key);
} else {
sameKeySynchronizer.serializeSameKeys(key, inputArgumentKey -> processInternal(inputArgumentKey));
}
}
#SuppressWarnings("MagicNumber")
private void processInternal(String key) {
try {
boolean keyInProgress = !keysInProgress.add(key);
if (keyInProgress) {
sameKeyInProgressSimultaneously = true;
}
try {
int sleepTimeInMillis = 100;
for (long elapsedTimeInMillis = 0; elapsedTimeInMillis < 1000; elapsedTimeInMillis += sleepTimeInMillis) {
Thread.sleep(sleepTimeInMillis);
if (keysInProgress.size() > 1) {
differentKeysInProgressSimultaneously = true;
}
}
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
} finally {
keysInProgress.remove(key);
}
}
}
}

Is it possible to get StackOverflowError without recursion?

I have a task to get "StackOverflowError" in java without using -Xss and recursion. I really don't have ideas... Only some nonsense like generating huge java class at runtime, compile it and invoke...
Java stores primitive types on the stack. Objects created in local scope are allocated on the heap, with the reference to them on the stack.
You can overflow the stack without recursion by allocating too many primitive types in method scope. With normal stack size settings, you would have to allocate an excessive number of variables to overflow.
Here is the implementation of Eric J. idea of generating excessive number of local variables using javassist library:
class SoeNonRecursive {
static final String generatedMethodName = "holderForVariablesMethod";
#SneakyThrows
Class<?> createClassWithLotsOfLocalVars(String generatedClassName, final int numberOfLocalVarsToGenerate) {
ClassPool pool = ClassPool.getDefault();
CtClass generatedClass = pool.makeClass(generatedClassName);
CtMethod generatedMethod = CtNewMethod.make(getMethodBody(numberOfLocalVarsToGenerate), generatedClass);
generatedClass.addMethod(generatedMethod);
return generatedClass.toClass();
}
private String getMethodBody(final int numberOfLocalVarsToGenerate) {
StringBuilder methodBody = new StringBuilder("public static long ")
.append(generatedMethodName).append("() {")
.append(System.lineSeparator());
StringBuilder antiDeadCodeEliminationString = new StringBuilder("long result = i0");
long i = 0;
while (i < numberOfLocalVarsToGenerate) {
methodBody.append(" long i").append(i)
.append(" = ").append(i).append(";")
.append(System.lineSeparator());
antiDeadCodeEliminationString.append("+").append("i").append(i);
i++;
}
antiDeadCodeEliminationString.append(";");
methodBody.append(" ").append(antiDeadCodeEliminationString)
.append(System.lineSeparator())
.append(" return result;")
.append(System.lineSeparator())
.append("}");
return methodBody.toString();
}
}
and tests:
class SoeNonRecursiveTest {
private final SoeNonRecursive soeNonRecursive = new SoeNonRecursive();
//Should be different for every case, or once generated class become
//"frozen" for javassist: http://www.javassist.org/tutorial/tutorial.html#read
private String generatedClassName;
#Test
void stackOverflowWithoutRecursion() {
generatedClassName = "Soe1";
final int numberOfLocalVarsToGenerate = 6000;
assertThrows(StackOverflowError.class, () -> soeNonRecursive
.createClassWithLotsOfLocalVars(generatedClassName, numberOfLocalVarsToGenerate));
}
#SneakyThrows
#Test
void methodGeneratedCorrectly() {
generatedClassName = "Soe2";
final int numberOfLocalVarsToGenerate = 6;
Class<?> generated = soeNonRecursive.createClassWithLotsOfLocalVars(generatedClassName, numberOfLocalVarsToGenerate);
//Arithmetic progression
long expected = Math.round((numberOfLocalVarsToGenerate - 1.0)/2 * numberOfLocalVarsToGenerate);
long actual = (long) generated.getDeclaredMethod(generatedMethodName).invoke(generated);
assertEquals(expected, actual);
}
}
EDIT:
The answer is incorrect, because it is one type of recursion. It is called indirect recursion https://en.wikipedia.org/wiki/Recursion_(computer_science)#Indirect_recursion.
I think the simplest way to do this without recursion is the following:
import java.util.LinkedList;
import java.util.List;
interface Handler {
void handle(Chain chain);
}
interface Chain {
void process();
}
class FirstHandler implements Handler {
#Override
public void handle(Chain chain) {
System.out.println("first handler");
chain.process();
}
}
class SecondHandler implements Handler {
#Override
public void handle(Chain chain) {
System.out.println("second handler");
chain.process();
}
}
class Runner implements Chain {
private List<Handler> handlers;
private int size = 5000; // change this parameter to avoid stackoverflowerror
private int n = 0;
public static void main(String[] args) {
Runner runner = new Runner();
runner.setHandlers();
runner.process();
}
private void setHandlers() {
handlers = new LinkedList<>();
int i = 0;
while (i < size) {
// there can be different implementations of handler interface
handlers.add(new FirstHandler());
handlers.add(new SecondHandler());
i += 2;
}
}
public void process() {
if (n < size) {
Handler handler = handlers.get(n++);
handler.handle(this);
}
}
}
At first glance this example looks a little crazy, but it's not as unrealistic as it seems.
The main idea of this approach is the chain of responsibility pattern. You can reproduce this exception in real life by implementing chain of responsibility pattern. For instance, you have some objects and every object after doing some logic call the next object in chain and pass the results of his job to the next one.
You can see this in java filter (javax.servlet.Filter).
I don't know detailed mechanism of working this class, but it calls the next filter in chain using doFilter method and after all filters/servlets processing request, it continue working in the same method below doFilter.
In other words it intercepts request/response before servlets and before sending response to a client.It is dangerous piece of code because all called methods are in the same stack at the same thread. Thus, it may initiate stackoverflow exception if the chain is too big or you call doFilter method on deep level that also provide the same situation. Perhaps, during debugging you might see chain of calls
in one thread and it potentially can be the cause of stackoverflowerror.
Also you can take chain of responsibility pattern example from links below and add collection of elements instead of several and you also will get stackoverflowerror.
Links with the pattern:
https://www.journaldev.com/1617/chain-of-responsibility-design-pattern-in-java
https://en.wikipedia.org/wiki/Chain-of-responsibility_pattern
I hope it was helpful for you.
Since the question is very interesting, I have tried to simplify the answer of hide :
public class Stackoverflow {
static class Handler {
void handle(Chain chain){
chain.process();
System.out.println("yeah");
}
}
static class Chain {
private List<Handler> handlers = new ArrayList<>();
private int n = 0;
private void setHandlers(int count) {
int i = 0;
while (i++ < count) {
handlers.add(new Handler());
}
}
public void process() {
if (n < handlers.size()) {
Handler handler = handlers.get(n++);
handler.handle(this);
}
}
}
public static void main(String[] args) {
Chain chain = new Chain();
chain.setHandlers(10000);
chain.process();
}
}
It's important to note that if stackoverflow occurs, the string "yeah" will never be output.
Of course we can do it :) . No recursion at all!
public static void main(String[] args) {
throw new StackOverflowError();
}
Looking at this answer below, not sure if this works for Java, but sounds like you can declare an array of pointers? Might be able to achieve Eric J's idea without requiring a generator.
Is it on the Stack or Heap?
int* x[LARGENUMBER]; // The addresses are held on the stack
int i; // On the stack
for(i = 0; i < LARGENUMBER; ++i)
x[i] = malloc(sizeof(int)*10); // Allocates memory on the heap

Mockito : Testing void methods gives InvalidUseOfMatchersException

I'm having problems with two void methods. In encouragedVenturesScoring I've followed this answer mocking an arraylist that will be looped in a for loop and haven't mocked the list, but passed a real list and added mocked objects.
Mockito gives me an InvalidUseOfMatchersException on this line
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
There are lots of questions on SO on this exception , and I think it's because of anyInt(). Anyway I changed it to
verify(effectList.get(0)).execute(playerHandler);
And now it's saying Wanted but not invoked effect.execute(playerHandler)
Actually there were zero interactions with this mock
Is it because I put doNothing ?
doNothing().when(effect).execute(playerHandler);
In my second method militaryStrengthScoring() method is there a way to skip the first chunk of code and just test the if..else condition? What would be the best approach to test this method?
Thank you for your time.
This is the class to be tested
public class EndGameScoringBaseController implements EndGameScoringHandler {
private static final int[] TERRITORIES_REWARD = {0,0,1,4,10,20};
private static final int[] CHARACTERS_REWARD = {1,3,6,10,15,21};
private static final int RESOURCES_RATE = 5;
private static final int FIRST_MILITARY_REWARD = 5;
private static final int SECOND_MILITARY_REWARD = 2;
private PlayerHandler player;
public EndGameScoringBaseController(PlayerHandler player) {
super();
this.player = player;
}
#Override
public void encouragedVenturesScoring() {
for (DevelopmentCard card : player.getPlayer().getPersonalBoard().getVentures()) {
for (Effect e : card.getPermanentEffects())
e.execute(player);
}
}
#Override
public void militaryStrengthScoring(GameController game) {
Set<Integer> points = new HashSet<>();
int myPoints = this.player.getPointsHandler().getMilitaryPoints();
for (PlayerHandler p: game.getPlayers()) {
points.add(p.getPointsHandler().getMilitaryPoints());
}
int[] rank = new int[points.size()];
int j = 0;
for (Integer i : points) {
rank[j] = i;
j++;
}
Arrays.sort(rank);
if (rank[rank.length-1] == myPoints) {
player.getPointsHandler().winMilitaryPoints(FIRST_MILITARY_REWARD);
}
else if (rank[rank.length-2] == myPoints) {
player.getPointsHandler().winVictoryPoints(SECOND_MILITARY_REWARD);
}
}
Tested method for encouragedVenturesScoring
#Test
public void encouragedVenturesScoringTest() {
//given
List<DevelopmentCard> ventureList;
ventureList = Arrays.asList(developmentCard, developmentCard);
when(playerHandler.getPlayer().getPersonalBoard().getVentures()).thenReturn(ventureList);
List<Effect> effectList;
effectList = Arrays.asList(effect, effect);
when(developmentCard.getPermanentEffects()).thenReturn(effectList);
doNothing().when(effect).execute(playerHandler);
//when
endgameController.encouragedVenturesScoring();
//then
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
}
Incomplete tested method for militaryStrengthScoring
#Test
public void militaryStrengthScoringTest() {
//given
when(playerHandler.getPointsHandler().getMilitaryPoints()).thenReturn(4);
doNothing().when(playerHandler.getPointsHandler()).winMilitaryPoints(FIRST_MILITARY_REWARD);
//when
endgameController.militaryStrengthScoring(gameController);
//then
/../
}
You're right that this is the problem:
verify(effectList.get(Mockito.anyInt())).execute(playerHandler);
Mockito only allows for calls like any() and anyInt() to stand in for parameters to the mock themselves, due to the internal implementation of matchers.
/* OK */ when(yourMock.yourMethod(anyInt())).thenReturn(42);
/* BAD */ when(yourList.get(anyInt()).yourMethod(0)).thenReturn(42);
/* OK */ verify(yourMock).yourMethod(anyInt());
/* BAD */ verify(yourList.get(anyInt())).yourMethod(0);
The failure with get(0) is likely an actual failure, and may be related to the fact that your encouragedVenturesScoringTest is actually not calling encouragedVenturesScoring, it's calling influencedCharactersScoring. If this continues to give you trouble after fixing that error, in ways related to Mockito, please edit your question.
You can only verify mock objects created by Mockito.
But effectList is a "real" list. Therefore Mockito knows nothing about that object. Thus any attempt to verify that list must fail.
If you want to verify that object - then you have to mock it!
Of course, this means that you have specify all calls that will go to the mocked list.

JUnit Test for Comparator in Java

How can I test the following class using JUnit testing. I am new to unit testing I just need a push to start
public class ComponentComparator implements Comparator< Component >
{
#Override
public int compare ( final Component c1, final Component c2 )
{
if ( c1.getBandwidthWithHeader() > c2.getBandwidthWithHeader() )
{
return -1;
}
else if ( c1.getBandwidthWithHeader() < c2.getBandwidthWithHeader() )
{
return 1;
}
return 0;
}
}
Part of the component class is, there is no constructor for this class
public class Component
{
private float bandwidthwithHeader;
public void setBandwidthWithHeader ( float bandwidthwithHeader )
{
this.bandwidthwithHeader = bandwidthwithHeader;
}
public float getBandwidthWithHeader ()
{
return this.bandwidthwithHeader;
}
}
You should go through some tutorial on JUnit.
Morfic's comment points to a good tutorial.
To begin with helping you with this - there are three possible return values from the comparator -> wrote a case for each one.
import org.junit.Assert;
import org.junit.Test;
public class ComponentComparatorTest {
#Test
public void testCompare() throws Exception {
ComponentComparator comparator = new ComponentComparator();
Assert.assertEquals(comparator.compare(new Component(1), new Component(1)), 0);
Assert.assertEquals(comparator.compare(new Component(2), new Component(1)), -1);
Assert.assertEquals(comparator.compare(new Component(1), new Component(2)), 1);
}
}
I am using a dummy class
public class Component {
int bandwidth;
public Component(int bandwidth) {
this.bandwidth = bandwidth;
}
public int getBandwidthWithHeader(){
return bandwidth;
}
}
The unit test should test all possible outcomes.
A comparator has three success outcomes.
You need to decide how you want to handle null parameter values (your current solution: NullPointerException).
Here is a unit test of your current comparator:
public class Component
{
private int bandwidthWithHeader;
public int getBandwidthWithHeader()
{
return bandwidthWithHeader;
}
public void setBandwidthWithHeader(final int newValue)
{
bandwidthWithHeader = newValue;
}
}
public class ComponentTest
{
private final ComponentComparator componentComparator = new ComponentComparator();
#Test
public void negative1()
{
Component two = new Component();
try
{
componentComparator.compare(null, two);
fail("Expected exception was not thrown");
}
catch(NullPointerException exception)
{
// The NullPointerException is the expected result.
assertTrue(true);
}
}
#Test
public void negative2()
{
Component one = new Component();
try
{
componentComparator.compare(one, null);
fail("Expected exception was not thrown");
}
catch(NullPointerException exception)
{
// The NullPointerException is the expected result.
assertTrue(true);
}
}
#Test
public void negative3()
{
try
{
componentComparator.compare(null, null);
fail("Expected exception was not thrown");
}
catch(NullPointerException exception)
{
// The NullPointerException is the expected result.
assertTrue(true);
}
}
#Test
public void positive1()
{
Component one = new Component();
Component two = new Component();
// test one < two
one.setBandwidthWithHeader(7);
two.setBandwidthWithHeader(16);
assertEquals(-1, componentComparator.compare(one, two);
// test two < one
one.setBandwidthWithHeader(17);
two.setBandwidthWithHeader(16);
assertEquals(1, componentComparator.compare(one, two);
// test two == one
one.setBandwidthWithHeader(25);
two.setBandwidthWithHeader(25);
assertEquals(0, componentComparator.compare(one, two);
}
}
How about something like this:
package mypackage;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
public class ComponentComparatorTestCase {
#Test
public void testCompareExpectZero() {
ComponentComparator sut = new ComponentComparator();
// create some components to test with
Component c1 = new Component();
Component c2 = new Component();
// execute test
int result = sut.compare(c1, c2);
// verify
assertEquals("Did not get expected result.", result, 0);
}
}
There are numerous tests you should do for any Comparator implementation.
First off, there is the fact that a Comparator should define (as stipulated in the Comparator contract) a total order on the given type.
This comes down to 3 things :
the order should be antisymmetric : if a ≤ b and b ≤ a then a = b
the order should be transitive : if a ≤ b and b ≤ c then a ≤ c
the order should be total : either a ≤ b or b ≤ a
Secondly, a Comparator implementation may choose to accept null values. So we need tests that verify whether null values are treated correctly, if accepted. Or if they are not accepted that they properly result in a NullPointerException being thrown.
Lastly, if the type being compared may be subclassed, it is worth testing that the comparator properly compares instances of various subclasses mixed with instances of the class itself. (You may need to define some subclasses in test scope for these tests)
As these tests tend to repeat for every Comparator implementation, it may be worth extracting them in an abstract test superclass.

Categories