Конструктор для проверки подлинности выводит избыточность и шаблон из теста на проверку.
Он знает, как создать объект Mock, потому что вы, конечно, говорите об этом (если только вы не имели в виду что-то еще с этим вопросом).
«Стандартный» способ создания фиктивного объекта - это использование / злоупотребление классом java.lang.reflect.Proxy для создания реализации интерфейса во время выполнения. Это делается во время выполнения. Прокси имеет ограничение в том, что он не может прокси конкретных классов. Для выполнения моделирования конкретных классов требуется динамическое создание байт-кода, которое создает подклассы, которые переопределяют реальную реализацию открытых методов, по существу, с тем, что было бы сделано с прокси-сервером (запишите параметры метода и верните предварительно определенное значение). Это имеет ограничение в том, что он не может создавать подклассы конечных классов. Для этого у вас есть такие решения, как JDave , которые (я полагаю, я не подтвердил это) смешивают с загрузчиком классов, чтобы удалить окончательное обозначение класса перед его загрузкой, поэтому класс не находится в окончательный факт во время выполнения, если речь идет о 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 для определения состояния безопасности и того, что возвращается.