diff --git a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/cache/SearchCache.java b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/cache/SearchCache.java
index 26aff5b31bb0f69ed69d721d538d1146edf634da..5eddfc57f6caaa23bed67eb4eaf407cc3136c16c 100644
--- a/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/cache/SearchCache.java
+++ b/openbis/source/java/ch/ethz/sis/openbis/generic/server/api/v3/cache/SearchCache.java
@@ -130,7 +130,7 @@ public class SearchCache<CRITERIA, FETCH_OPTIONS, OBJECT> implements ISearchCach
         return getCacheManager().getCache(CACHE_NAME);
     }
 
-    private long getCacheSize()
+    protected long getCacheSize()
     {
         String propertyValue = getSystemProperty(CACHE_SIZE_PROPERTY_NAME);
 
@@ -164,7 +164,7 @@ public class SearchCache<CRITERIA, FETCH_OPTIONS, OBJECT> implements ISearchCach
         }
     }
 
-    private long getCacheDefaultSize()
+    protected long getCacheDefaultSize()
     {
         long memorySize = getMemorySize();
         long cacheSize = memorySize / 4;
diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractSearchMethodExecutorStressTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractSearchMethodExecutorStressTest.java
index 66f736722903c97f6ff23ee8bb013b049a3c5246..b5e935c78402e1b6fa5e06214b565b800fb9b0ff 100644
--- a/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractSearchMethodExecutorStressTest.java
+++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/generic/server/api/v3/executor/method/AbstractSearchMethodExecutorStressTest.java
@@ -27,6 +27,7 @@ import java.util.UUID;
 
 import net.sf.ehcache.CacheManager;
 
+import org.apache.commons.io.FileUtils;
 import org.testng.Assert;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -55,6 +56,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
 /**
  * @author pkupczyk
  */
+@SuppressWarnings({ "unchecked", "rawtypes" })
 public class AbstractSearchMethodExecutorStressTest
 {
 
@@ -64,105 +66,145 @@ public class AbstractSearchMethodExecutorStressTest
         LogInitializer.init();
     }
 
-    @SuppressWarnings({ "unchecked", "rawtypes" })
     @Test
-    public void testMultipleThreads() throws InterruptedException
+    public void testConcurrencyWithoutEvicting() throws InterruptedException
     {
-        int SESSION_COUNT = 5;
-        int THREAD_COUNT = 5;
-        int KEY_VERSION_COUNT = 20;
-        int RUN_COUNT = 5;
-
-        for (int r = 0; r < RUN_COUNT; r++)
+        for (int run = 0; run < 5; run++)
         {
-            final TestSearchMethodExecutor executor = new TestSearchMethodExecutor();
+            TestSearchMethodExecutor executor = testConcurrency(0);
 
-            final List<String> sessionTokens = new ArrayList<String>();
-            for (int s = 0; s < SESSION_COUNT; s++)
+            for (Map.Entry<SearchCacheKey, Integer> entry : executor.getSearchCounts().entrySet())
             {
-                Session session = new Session("user" + s, "token" + s, new Principal(), "", 1);
-                sessionTokens.add(session.getSessionToken());
-                executor.addSession(session.getSessionToken(), session);
+                if (entry.getValue() != 1)
+                {
+                    executor.addError("Run " + run + " : " + entry.getValue() + " searches were executed instead of 1 for the key " + entry.getKey());
+                }
             }
 
-            final List<SearchCacheKey> keys = new ArrayList<SearchCacheKey>();
-            for (String sessionToken : sessionTokens)
+            if (executor.getErrors().size() > 0)
             {
-                for (int k = 0; k < KEY_VERSION_COUNT; k++)
-                {
-                    SpaceSearchCriteria spaceSearchCriteria = new SpaceSearchCriteria();
-                    spaceSearchCriteria.withCode().thatEquals(String.valueOf(k));
-                    keys.add(new SearchCacheKey(sessionToken, spaceSearchCriteria, new SpaceFetchOptions().cacheMode(CacheMode.CACHE)));
-
-                    ProjectSearchCriteria projectSearchCriteria = new ProjectSearchCriteria();
-                    projectSearchCriteria.withCode().thatEquals(String.valueOf(k));
-                    keys.add(new SearchCacheKey(sessionToken, projectSearchCriteria, new ProjectFetchOptions().cacheMode(CacheMode.CACHE)));
+                Assert.fail(String.join("\n", executor.getErrors()));
+            }
+        }
+    }
 
-                    ExperimentSearchCriteria experimentSearchCriteria = new ExperimentSearchCriteria();
-                    experimentSearchCriteria.withCode().thatEquals(String.valueOf(k));
-                    keys.add(new SearchCacheKey(sessionToken, experimentSearchCriteria, new ExperimentFetchOptions().cacheMode(CacheMode.CACHE)));
+    @Test
+    public void testConcurrencyWithEvicting() throws InterruptedException
+    {
+        for (int run = 0; run < 5; run++)
+        {
+            TestSearchMethodExecutor executor = testConcurrency(10 * FileUtils.ONE_KB);
 
-                    SampleSearchCriteria sampleSearchCriteria = new SampleSearchCriteria();
-                    sampleSearchCriteria.withCode().thatEquals(String.valueOf(k));
-                    keys.add(new SearchCacheKey(sessionToken, sampleSearchCriteria, new SampleFetchOptions().cacheMode(CacheMode.CACHE)));
-                }
+            if (executor.getErrors().size() > 0)
+            {
+                Assert.fail(String.join("\n", executor.getErrors()));
             }
+        }
+    }
+
+    private TestSearchMethodExecutor testConcurrency(long cacheSize) throws InterruptedException
+    {
+        int SESSION_COUNT = 5;
+        int THREAD_COUNT = 5;
+        int KEY_VERSION_COUNT = 20;
 
-            List<Thread> threads = new ArrayList<Thread>();
+        final TestSearchMethodExecutor executor = new TestSearchMethodExecutor(cacheSize);
 
-            for (int t = 0; t < THREAD_COUNT; t++)
+        final List<String> sessionTokens = new ArrayList<String>();
+        for (int s = 0; s < SESSION_COUNT; s++)
+        {
+            Session session = new Session("user" + s, "token" + s, new Principal(), "", 1);
+            sessionTokens.add(session.getSessionToken());
+            executor.addSession(session.getSessionToken(), session);
+        }
+
+        final List<SearchCacheKey> keys = new ArrayList<SearchCacheKey>();
+        for (String sessionToken : sessionTokens)
+        {
+            for (int k = 0; k < KEY_VERSION_COUNT; k++)
             {
-                threads.add(new Thread(new Runnable()
+                SpaceSearchCriteria spaceSearchCriteria = new SpaceSearchCriteria();
+                spaceSearchCriteria.withCode().thatEquals(String.valueOf(k));
+                SearchCacheKey spaceKey =
+                        new SearchCacheKey(sessionToken, spaceSearchCriteria, new SpaceFetchOptions().cacheMode(CacheMode.CACHE));
+                keys.add(spaceKey);
+                executor.setSearchResult(spaceKey, new RandomSizeArray(cacheSize));
+
+                ProjectSearchCriteria projectSearchCriteria = new ProjectSearchCriteria();
+                projectSearchCriteria.withCode().thatEquals(String.valueOf(k));
+                SearchCacheKey projectKey =
+                        new SearchCacheKey(sessionToken, projectSearchCriteria, new ProjectFetchOptions().cacheMode(CacheMode.CACHE));
+                keys.add(projectKey);
+                executor.setSearchResult(projectKey, new RandomSizeArray(cacheSize));
+
+                ExperimentSearchCriteria experimentSearchCriteria = new ExperimentSearchCriteria();
+                experimentSearchCriteria.withCode().thatEquals(String.valueOf(k));
+                SearchCacheKey experimentKey =
+                        new SearchCacheKey(sessionToken, experimentSearchCriteria, new ExperimentFetchOptions().cacheMode(CacheMode.CACHE));
+                keys.add(experimentKey);
+                executor.setSearchResult(experimentKey, new RandomSizeArray(cacheSize));
+
+                SampleSearchCriteria sampleSearchCriteria = new SampleSearchCriteria();
+                sampleSearchCriteria.withCode().thatEquals(String.valueOf(k));
+                SearchCacheKey sampleKey =
+                        new SearchCacheKey(sessionToken, sampleSearchCriteria, new SampleFetchOptions().cacheMode(CacheMode.CACHE));
+                keys.add(sampleKey);
+                executor.setSearchResult(sampleKey, new RandomSizeArray(cacheSize));
+            }
+        }
+
+        List<Thread> threads = new ArrayList<Thread>();
+
+        for (int t = 0; t < THREAD_COUNT; t++)
+        {
+            threads.add(new Thread(new Runnable()
+                {
+                    @Override
+                    public void run()
                     {
-                        @Override
-                        public void run()
+                        for (int i = 0; i < keys.size() * 2; i++)
                         {
-                            for (int i = 0; i < keys.size() * 2; i++)
+                            SearchCacheKey key = keys.get((int) (Math.random() * keys.size()));
+                            SearchResult searchResult = executor.search(key.getSessionToken(), key.getCriteria(), key.getFetchOptions());
+
+                            Object actualResult = searchResult.getObjects().get(0);
+                            Object expectedResult = executor.getSearchResult(key);
+
+                            if (false == actualResult.equals(expectedResult))
                             {
-                                SearchCacheKey key = keys.get((int) (Math.random() * keys.size()));
-                                SearchResult searchResult = executor.search(key.getSessionToken(), key.getCriteria(), key.getFetchOptions());
-                                Assert.assertEquals(searchResult.getObjects().get(0), key);
+                                executor.addError("Actual search result: " + actualResult + " but expected: " + expectedResult + " for key: "
+                                        + key);
                             }
-
                         }
-                    }));
-            }
-
-            for (Thread thread : threads)
-            {
-                thread.start();
-            }
 
-            for (Thread thread : threads)
-            {
-                thread.join();
-            }
+                    }
+                }));
+        }
 
-            StringBuilder error = new StringBuilder();
-            for (Map.Entry<SearchCacheKey, Integer> entry : executor.getSearchCounts().entrySet())
-            {
-                if (entry.getValue() != 1)
-                {
-                    error.append("Run " + r + " : " + entry.getValue() + " searches were executed instead of 1 for the key " + entry.getKey()
-                            + "\n");
-                }
-            }
+        for (Thread thread : threads)
+        {
+            thread.start();
+        }
 
-            if (error.length() > 0)
-            {
-                Assert.fail(error.toString());
-            }
+        for (Thread thread : threads)
+        {
+            thread.join();
         }
+
+        return executor;
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private class TestSearchMethodExecutor extends AbstractSearchMethodExecutor
+    private static class TestSearchMethodExecutor extends AbstractSearchMethodExecutor
     {
         private Map<String, Session> sessions = new HashMap<>();
 
         private Map<SearchCacheKey, Integer> searchCounts = new HashMap<>();
 
-        public TestSearchMethodExecutor()
+        private Map<SearchCacheKey, Object> searchResults = new HashMap<>();
+
+        private List<String> errors = Collections.synchronizedList(new ArrayList<String>());
+
+        public TestSearchMethodExecutor(final long cacheSize)
         {
             String managerConfig = "<ehcache name='" + UUID.randomUUID() + "'></ehcache>";
             final CacheManager manager = new CacheManager(new ByteArrayInputStream(managerConfig.getBytes()));
@@ -174,7 +216,20 @@ public class AbstractSearchMethodExecutorStressTest
                     {
                         return manager;
                     }
+
+                    @Override
+                    protected long getCacheSize()
+                    {
+                        if (cacheSize > 0)
+                        {
+                            return cacheSize;
+                        } else
+                        {
+                            return super.getCacheSize();
+                        }
+                    }
                 };
+
             theCache.initCache();
             this.cache = theCache;
         }
@@ -200,7 +255,7 @@ public class AbstractSearchMethodExecutorStressTest
                 throw new RuntimeException(e);
             }
 
-            return Collections.singleton(key);
+            return Collections.singleton(searchResults.get(key));
         }
 
         public Map<SearchCacheKey, Integer> getSearchCounts()
@@ -208,6 +263,16 @@ public class AbstractSearchMethodExecutorStressTest
             return searchCounts;
         }
 
+        public void setSearchResult(SearchCacheKey key, Object result)
+        {
+            searchResults.put(key, result);
+        }
+
+        public Object getSearchResult(SearchCacheKey key)
+        {
+            return searchResults.get(key);
+        }
+
         void addSession(String sessionToken, Session session)
         {
             sessions.put(sessionToken, session);
@@ -219,6 +284,16 @@ public class AbstractSearchMethodExecutorStressTest
             return sessions.get(sessionToken);
         }
 
+        public void addError(String error)
+        {
+            errors.add(error);
+        }
+
+        public List<String> getErrors()
+        {
+            return errors;
+        }
+
         @Override
         protected ISearchObjectExecutor getSearchExecutor()
         {
@@ -245,4 +320,35 @@ public class AbstractSearchMethodExecutorStressTest
 
     }
 
+    private static class RandomSizeArray
+    {
+
+        private byte[] array;
+
+        public RandomSizeArray(long maxSize)
+        {
+            array = new byte[(int) (Math.random() * maxSize)];
+        }
+
+        @Override
+        public int hashCode()
+        {
+            return array.length;
+        }
+
+        @Override
+        public boolean equals(Object obj)
+        {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            RandomSizeArray other = (RandomSizeArray) obj;
+            return array.length == other.array.length;
+        }
+
+    }
+
 }