У меня есть класс Singleton для теста:JMockit: Singleton класс Заказать тест
public class Singleton {
private static Singleton instance;
private List<String> list;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
public boolean methodOne() {
if (list == null) {
list = new ArrayList<String>();
list = SomeClass.fillListOne();
}
return SomeClass.verifyList(list);
}
public boolean methodTwo() {
if (list == null) {
list = new ArrayList<String>();
list = SomeClass.fillListTwo();
}
return SomeClass.verifyList(list);
}
}
С следующего теста:
@RunWith(JMockit.class)
public class SingletonTest {
@Test
public void testOne(final @Mocked SomeClass someClass) {
Singleton.getInstance().methodOne();
new Verifications() {
{
SomeClass.fillListOne();
}
};
}
@Test
public void testTwo(final @Mocked SomeClass someClass) {
Singleton.getInstance().methodTwo();
new Verifications() {
{
SomeClass.fillListTwo();
}
};
}
}
Если я выполняю только "testOne" или только «testTwo », проходят тесты. Если я выполняю все тесты, он передает только первый выполненный метод. Как установить атрибут «list» равным null, например, в методе @Before? Как использовать Deencapsulation с Singleton или частным членом без сеттеров?
FYI: метод getInstance невероятно опасен. Вы не можете синхронизировать внутри нулевой проверки и ожидать, что она будет безопасной. Входит Thread A и проверяет, не является ли экземпляр экземпляром null, но это не так. Контекстный коммутатор, Thread B входит, чтобы проверить, является ли экземпляр нулевым, он все еще не так продолжается. Thread B получает блокировку и инициализирует некоторый объект, присваивает его экземпляру (который гарантированно назначается и инициализируется в соответствии с требованиями синхронизации) и освобождает блокировку. Контекстный коммутатор Thread A теперь получает блокировку и делает то же самое, переписывая экземпляр из ThreadB. – searchengine27
рекомендуется прочитать для разработчиков Java-совместимости: http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html (вы сделали самую первую ошибку, подробно описанную здесь) – searchengine27
Уточнение: "(что гарантировано быть назначенным и инициализированным в соответствии с требованиями синхронизации) »означает, что к моменту освобождения блокировки гарантируется, что объект будет назначен и инициализирован. Порядок, который происходит внутри синхронизированного блока, не является детерминированным, для JMM. Для дальнейшего уточнения ваш пример становится жертвой этого, но также становится жертвой моего первоначального примера (который не имеет отношения к JMM, но зная, как JMM справится с этим, облегчит ваше «решение» этой проблемы, которое имеет ссылку I размещены детали, почему это не сработает). – searchengine27