Вот мой подход. Этот тест не связан с тупиками, он связан с согласованностью. Я тестирую метод с синхронизированным блоком, с кодом, который выглядит примерно так:
synchronized(this) {
int size = myList.size();
// do something that needs "size" to be correct,
// but which will change the size at the end.
...
}
Трудно создать сценарий, который надежно приведет к конфликту потоков, но вот что я сделал.
Во-первых, мой модульный тест создал 50 потоков, запустил их все одновременно и заставил всех вызывать мой метод. Я использую CountDown Latch, чтобы запустить их все одновременно:
CountDownLatch latch = new CountDownLatch(1);
for (int i=0; i<50; ++i) {
Runnable runner = new Runnable() {
latch.await(); // actually, surround this with try/catch InterruptedException
testMethod();
}
new Thread(runner, "Test Thread " +ii).start(); // I always name my threads.
}
// all threads are now waiting on the latch.
latch.countDown(); // release the latch
// all threads are now running the test method at the same time.
Это может или не может привести к конфликту. Мой метод testMethod () должен быть в состоянии генерировать исключение в случае возникновения конфликта. Но мы пока не можем быть уверены, что это вызовет конфликт. Поэтому мы не знаем, является ли тест действительным. Итак, вот хитрость: Закомментируйте ваши синхронизированные ключевые слова и запустите тест. Если это вызовет конфликт, тест не пройден. Если произойдет сбой без синхронизированного ключевого слова, ваш тест действителен.
Это то, что я сделал, и мой тест не провалился, поэтому он (пока) не был действительным. Но я смог надежно создать ошибку, поместив приведенный выше код в цикл и выполнив его 100 раз подряд. Поэтому я называю метод 5000 раз. (Да, это приведет к медленному тесту. Не беспокойтесь об этом. Ваши клиенты не будут беспокоиться об этом, поэтому вы тоже не должны.)
Как только я поместил этот код во внешний цикл, я смог надежно увидеть сбой на 20-й итерации внешнего цикла. Теперь я был уверен, что тест был действительным, и восстановил синхронизированные ключевые слова, чтобы запустить реальный тест. (Это сработало.)
Вы можете обнаружить, что тест действителен на одном компьютере, а не на другом. Если тест действителен на одной машине, и ваши методы проходят его, то он предположительно является поточно-ориентированным на всех машинах. Но вы должны проверить правильность на компьютере, на котором выполняются ваши ночные юнит-тесты.