Вот немного из документации Мокито:
39. Mocking финальных типов, перечислений и финальных методов (начиная с 2.1.0)
Mockito теперь предлагает инкубационную, опциональную поддержку для насмешливых финальных классов и методов. Это фантастическое улучшение, которое демонстрирует вечный поиск Mockito для улучшения опыта тестирования. Мы стремимся к тому, чтобы Mockito «просто работал» с финальными классами и методами. Ранее они считались немодными, что не позволяло пользователю издеваться. Мы уже начали обсуждать, как включить эту функцию по умолчанию. В настоящее время эта функция по-прежнему не является обязательной, поскольку мы ожидаем дополнительных отзывов от сообщества.
Эта функция по умолчанию отключена, поскольку она основана на совершенно другом механизме насмешек, который требует большей обратной связи от сообщества.
Однако я бы скорее рекомендовал заменить синглтон перечисления на синглтон статического члена в одноэлементном классе, поскольку его часто считают более читабельным, в равной степени потокобезопасным и более настраиваемым, как показывает этот тестовый пример.
Примерно так:
public class Y {
private Y() {}
private final static Y y = new Y();
public static Y getInstance() {
return y;
}
public boolean someMethod() {
return true;
}
}
enum X {
INSTANCE;
private final Y y = Y.getInstance();
public boolean isfunc() {
return y.someMethod();
}
}
public class XTest {
@Mock private Y yMock;
@Before
public void setUp() throws Exception {
Whitebox.setInternalState(X.INSTANCE, "y", yMock);
}
@Test
void test() { // ...
}
}
Я бы добавил, что мне не нравится использовать Whitebox во время тестов. Я считаю, что все, что может сделать тест, мой код должен уметь делать, так как тест является первым реальным клиентом моего модуля и индикатором того, что могут захотеть делать будущие клиенты. Например, так же, как тест хотел бы заменить Y на фиктивный Y, в будущем кто-то может захотеть использовать X с другим производственным Y.
Я бы изменил Y, чтобы использовать интерфейс, и удалил быfinal для переменной y в X, чтобы сделать ее настраиваемой, следующим образом:
interface IY
{
public boolean someMethod();
}
public class Y implements IY {
private Y() {}
private final static IY y = new Y();
public static IY getInstance() {
return y;
}
public boolean someMethod() {
return true;
}
}
enum X {
INSTANCE;
private IY y = Y.getInstance();
public void setY(IY y)
{
this.y = y;
}
public boolean isfunc() {
return y.someMethod();
}
}
public class XTest {
@Mock private Y yMock;
@Before
public void setUp() throws Exception {
X.INSTANCE.setY(yMock);
}
@Test
void test() { // ...
}
}
Я бы пожертвовал некоторой безопасностью (например, возможностью X.INSTANCE.setY (null);) для конфигурируемостии чистый код.