Как платформы насмешки Java работают?

Это не вопрос, о котором лучшая платформа, и т.д.

Я никогда не использовал платформу насмешки, и я немного озадачен идеей. Как это знает, как создать фиктивный объект? Это сделано во времени выполнения, или это генерирует файл? Как Вы знаете его поведение? И самое главное – каков рабочий процесс использования такой платформы (каково пошаговое для создания теста)?

Кто-либо может объяснить? Можно выбрать, какой бы ни платформа, которую Вы любите, например, просто говорят, каково это.

24
задан Boann 4 March 2017 в 01:00
поделиться

5 ответов

Я буду говорить о фреймворке, который я использую (jmock), но другие делают нечто очень похожее.

Откуда он знает, как создавать фиктивный объект?

Это не так, вы говорите фреймворку, что вам нужен фиктивный объект, и вы указываете ему тип (в идеале - интерфейс) объекта, который вы хотели бы имитировать. За кулисами фиктивный фреймворк использует комбинацию отражения и, иногда, переписывания байт-кода для создания фиктивного объекта.

Это делается во время выполнения или генерирует файл?

jMock создает его во время выполнения.

Как узнать его поведение?

Поддельные объекты довольно тупые. Вы указываете поведение, которое вы от них ожидаете.

И самое главное - какой рабочий процесс использования такого фреймворка (каковы пошаговые инструкции по созданию тест).

Одна очень важная вещь, которую должен предоставить фреймворк, - это возможность проверять, наблюдается ли ожидаемое поведение во время выполнения теста.

jmock делает это путем введения специального средства запуска тестов, которое проверяет выполнение всех ожиданий для всех объявленных фиктивных объектов после завершения теста. Если что-то не совпадает, генерируется исключение.

Обычно используется следующий шаблон:

  1. Получите фиктивную фабрику (называемую Mockery в jmock) из воздуха (с помощью специального конструктора без аргументов).
  2. Создание требуемых имитационных объектов.
  3. Настройка ожидания для фиктивных объектов
  4. Вызов тестируемого метода, передача фиктивных объектов вместо реальных
  5. Если ваш метод возвращает некоторые значения, проверьте ожидаемое значение с помощью обычных методов assertXXX .
11
ответ дан 28 November 2019 в 23:57
поделиться

Я думаю, что документация EasyMock - это хороший способ начать работу. В нем много примеров, которые легко понять.

1
ответ дан 28 November 2019 в 23:57
поделиться

Для лучшего понимания mocking, вы можете сделать свой собственный mock-объект. Это довольно простой процесс - вы создаете класс, который реализует тот же интерфейс, что и объект, над которым вы насмехаетесь, и задаете ему требуемое поведение, либо записывая вызовы метода, либо реагируя определенным образом на вызов. Отсюда то, как устроены фреймворки насмешек, начинает обретать смысл.

5
ответ дан 28 November 2019 в 23:57
поделиться

EasyMock (http://easymock.org/) - это библиотека мокинга, которую я использовал чаще всего. (Есть и другие: jMock, Mockito и т.д.)

Большинство из них создают объект во время выполнения, которым вы можете управлять. Основная схема такова:

  1. Создайте имитатор
  2. Укажите, как он должен действовать, сообщив фреймворку имитатора, какие вызовы ожидать. (Это зависит от фреймворка)
  3. Используйте имитатор в своем тесте, как если бы это был настоящий объект
  4. Некоторые фреймворки позволяют (или требуют), чтобы вы "проверили", что имитатор был использован правильно.
0
ответ дан 28 November 2019 в 23:57
поделиться

Фреймворк mocking исключает избыточность и шаблонизатор из теста mocking.

Он знает, как создать объект Mock, потому что вы, конечно же, говорите ему (если вы не имели в виду что-то другое в этом вопросе).

«Стандартный» способ создания фиктивного объекта - использовать / злоупотреблять классом java.lang.reflect.Proxy для создания реализации интерфейса во время выполнения. Это делается во время выполнения. Прокси имеет ограничение в том, что он не может проксировать конкретные классы. Чтобы выполнить имитацию конкретных классов, требуется создание динамического байт-кода, который создает подклассы, которые переопределяют реальную реализацию общедоступных методов, по сути, тем, что было бы сделано с помощью прокси (записывать параметры метода и возвращать заранее определенное значение). Это имеет ограничение в том, что он не может создавать подклассы финальных классов. Для этого у вас есть такие решения, как JDave , которые (я полагаю, я не подтверждал это) смешивают с загрузчиком классов, чтобы удалить окончательное обозначение класса перед его загрузкой, поэтому класс не находится в факт final во время выполнения, что касается JVM.

Фреймворк Mocking в основном предназначен для сбора параметров и их проверки на соответствие заранее определенным ожиданиям, а затем возврата предварительно сконфигурированного или разумного значения по умолчанию. Он не ведет себя каким-то определенным образом, вот в чем дело. Вызывающий код проверяется на предмет того, что он вызывает метод с правильным параметром и, возможно, как он реагирует на определенные возвращаемые значения или выданные исключения. Никаких побочных эффектов или реальных достижений при обращении к реальному объекту не происходит.

Вот реальный пример из проекта с использованием JMock с JUnit4. Я добавил комментарии, чтобы объяснить, что происходит.

 @RunWith(JMock.class) //The JMock Runner automatically checks that the expectations of the mock were actually run at the end of the test so that you don't have to do it with a line of code in every test.
public class SecuredPresentationMapTest {

private Mockery context = new JUnit4Mockery(); //A Mockery holds the state about all of the Mocks. The JUnit4Mockery ensures that a failed mock throws the same Error as any other JUnit failure.

@Test
public void testBasicMap() {
    final IPermissionsLookup lookup = context.mock(IPermissionsLookup.class); //Creating a mock for the interface IPermissionsLookup.
    context.checking(new Expectations(){{ //JMock uses some innovative but weird double brace initialization as its standard idom.
        oneOf(lookup).canRead(SecuredEntity.ACCOUNTING_CONTRACT);
            //expect exactly one call to the IPermissionsLookup.canRead method with the the enum of ACCOUNTING_CONTRACT as the value. Failure to call the method at all causes the test to fail.
            will(returnValue(true)); //when the previous method is called correctly, return true;
    }});

    Map<String, Component> map = new SecuredPresentationMap(lookup, SecuredEntity.ACCOUNTING_CONTRACT);
    //This creates the real object under test, but passes a mock lookup rather than the real implementation.
    JLabel value = new JLabel();
    map.put("", value);
    assertThat(((JLabel) map.get("")), is(value)); //This ensures that the Map returns the value placed, which it should based on the fact that the mock returned true to the security check.
  }
}

Если бы пройденный макет был проигнорирован, тест не прошел бы. Если карта не может вернуть помещенное в нее значение, тест не выполняется (это стандартный JUnit).

Здесь и в другом противоположном тесте проверяется то, что в зависимости от того, что интерфейс IPermissionsLookup говорит о безопасности, карта меняет свое поведение в отношении того, что возвращается. Это основной хороший случай. Другой тест, макет возвращает false, и от карты ожидается что-то еще. Использование макета гарантирует, что карта полагается на метод IPermissionsLookup для определения состояния безопасности и того, что возвращается.

16
ответ дан 28 November 2019 в 23:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: