TestableMock
Он улучшен на основе исходного кода и байт-кода.JavaМодульное Вспомогательный инструмент для обучения, включает в себя следующие функции:
В настоящее время споры о том, нужно ли проводить модульное тестирование частных методов, постепенно затихают, и общепринятая практика разработчиков дала фактический ответ. Во многих случаях сложно косвенно тестировать частные методы с помощью общедоступных. Разработчики предпочитают сделать изначально частные методы тестируемыми в тестовых примерах, изменив видимость метода.
Кроме того, при модульном тестировании часто необходимо инициализировать определенные поля-члены тестируемого объекта, но иногда из-за ограничений метода-конструктора тестируемого класса не представляется возможным удобно присвоить этим значениям значения. поля. Итак, можно ли разрешить коду в примере модульного тестирования иметь прямой доступ к частным методам и полям-членам тестируемого класса, не разрушая инкапсуляцию тестируемого типа? TestableMock предоставляет два простых решения.
@EnablePrivateAccess
аннотацияПросто длятест Добавление класса@EnablePrivateAccess
аннотация,В сценарии использования вы можете получить следующие расширенные возможности тестирования:
При доступе к частным постоянным членам и их изменении IDE может выдать синтаксические ошибки, но компилятор сможет нормально выполнить тест. (Используя улучшение кода во время компиляции, в настоящее время реализована только адаптация к языку Java)
Посмотрите эффектjava-demo
Пример проектаDemoPrivateAccessTest
тест Варианты использования в классах。
PrivateAccessor
инструментдобрыйЕсли вы не хотите видеть напоминание о синтаксической ошибке в среде IDE,Или в проекте JVM, отличном от Java (например, на языке Kotlin).,Вы также можете использоватьPrivateAccessor
инструментдобрыйдля прямого доступа к частным членам。
Этот класс предоставляет 6 статических методов:
PrivateAccessor.get(проверяемый объект, «Имя частного поля»)
➜ Чтение частных полей тестируемого классаPrivateAccessor.set(тестируемый объект, «Имя частного поля», новое значение)
➜ Измените частные поля (или постоянные поля) тестируемого класса.PrivateAccessor.invoke(проверяемый объект, «Имя частного метода», Параметры вызова..)
➜ Вызов частного метода тестируемого классаPrivateAccessor.getStatic(проверяемый тип, "Имя частного статического поля")
➜ Прочитать тестдобрыйизстатическийличное полеPrivateAccessor.setStatic(проверяемый тип, "Имя частного статического поля", новое значение)
➜ Изменить проверенноедобрыйизстатическийличное поле(илистатическийпостоянные поля)PrivateAccessor.invokeStatic(проверяемый тип, "Имя частного статического метода", Параметры вызова..)
➜ вызовпроверенодобрыйизстатическийчастныйметодПо сравнению с предыдущим методом Mock, Mock использует классы в качестве детализации.,TestableMock
Позвольте пользователям напрямую определять потребностиMockиз单个метод,и следуйте принципу соглашения над конфигурацией,Автоматически заменять указанные вызовы методов в тестируемом методе во время выполнения в соответствии с правилами.
Подводя итог, их два:
@MockMethod
аннотация@MockContructor
аннотацияКонкретное соглашение об определении метода Mock выглядит следующим образом:
существоватьтестдобрыйвнутриопределить@MockMethod
аннотацияиз普通метод,Сделайте его точно таким же, как имя метода, параметры и тип возвращаемого значения, которые необходимо переопределить.,Затемсуществовать Чтопараметр Добавлено в начало спискадобавлятьодиндобрый Типметодизначально принадлежалвернослондобрый型изпараметр。
В это время все вызовы переопределяемого метода в тестируемом классе будут автоматически заменены вызовами вышеупомянутого пользовательского метода Mock при запуске модульного теста.
Уведомление:При столкновении с перезаписьюметод Когда есть повторяющиеся имена,可以将需覆写изметодимя, написанное для@MockMethod
аннотацияизtargetMethod
параметрвнутри,Таким образом, сам метод Mock может быть назван произвольно.
Например,проверенодобрый Есть место в"anything".substring(1, 2)
вызов,Мы надеемся изменить его на фиксированную строку при запуске теста.,Затем просто определите следующий метод в тестовом классе:
// Исходная сигнатура метода — `String substring(int, int)`
// Объект «что-нибудь», для которого вызывается этот метод, имеет тип «String».
// Затем сигнатура метода Mock добавляет параметр типа String (имя произвольное) в начало списка параметров.
// Этот параметр можно использовать для получения значения и контекста фактического вызывающего абонента в данный момент.
@MockMethod
private String substring(String self, int i, int j) {
return "sub_string";
}
Следующий пример показываетtargetMethod
параметр Использование,Эффект тот же, что и в приведенном выше примере:
// Используйте targetMethod, чтобы указать имя метода, который будет издеваться.
// Сам метод теперь можно назвать как угодно, но параметры метода по-прежнему должны соответствовать тем же правилам соответствия.
@MockMethod(targetMethod = "substring")
private String use_any_mock_method_name(String self, int i, int j) {
return "sub_string";
}
Посмотреть полный пример кодаjava-demo
иkotlin-demo
Пример проектасерединаизshould_able_to_mock_common_method()
тествариант использования。(потому чтоKotlinверноStringдобрый Модель была магически модифицирована.,ПоэтомуKotlin示例середина将проверенометодсуществоватьBlackBox
добрыйвнутридобавлятьслой упаковки)
Иногда при тестировании определенных методов вы хотите смоделировать другие методы-члены тестируемого класса.
Метод операции такой же, как и в предыдущем случае. Первый тип параметра метода Mock должен совпадать с типом тестируемого класса, чтобы можно было переопределить метод-член самого тестируемого класса (публичный или частный). .
Например,проверенодобрыйсередина有один Подписано какString innerFunc(String)
изчастныйметод,Мы хотим заменить его, когда тест,Затем просто определите следующий метод в тестовом классе:
// Тестируемый тип — «DemoMock».
// Поэтому при определении метода Mock добавьте параметр типа DemoMock (имя произвольное) в начало параметра целевого метода.
@MockMethod
private String innerFunc(DemoMock self, String text) {
return "mock_" + text;
}
Mock для статического метода такой же, как и для обычного метода. Но что нужно Уведомлению, так это,Когда вызывается метод Mock статического метода,Первый прошел впараметр Фактическое значение всегдаnull
。
Например,существоватьпроверенодобрыйсерединавызов ПонятноBlackBox
добрый型серединаизстатическийметодsecretBox()
,изменятьметод Подписано какBlackBox secretBox()
,Метод Mock заключается в следующем:
// Целевой статический метод определен в типе BlackBox.
// При определении метода Mock добавьте параметр типа BlackBox (имя произвольное) в начале параметра целевого метода.
// Этот параметр используется только для определения типа цели, фактическое входящее значение всегда будет нулевым.
@MockMethod
private BlackBox secretBox(BlackBox ignore) {
return new BlackBox("not_secret_box");
}
Посмотреть полный пример кодаjava-demo
иkotlin-demo
Пример проектасерединаизshould_able_to_mock_static_method()
тествариант использования。
Как тестировать методы типа void, всегда было темой, которую многие платформы модульного тестирования незаметно избегали. Поскольку предыдущие методы модульного тестирования в основном проверяли возвращаемые результаты тестируемого модуля, ситуация изменится, когда метод не возвращает значение. Нет. способ начать.
С функциональной точки зрения, хотя метод void не возвращает никакого значения, его выполнение определенно окажет некоторое потенциальное влияние на внешний мир. Мы называем это «побочным эффектом» метода, например:
Метод, который не возвращает никакого значения и не производит никаких «побочных эффектов», не имеет смысла.
Эти"побочный эффект"из本质归纳来说可分为两добрый:Изменить внешние переменныеиВызов внешнего метода。
Благодаря доступу к частным полям TestableMock и валидатору Mock вы можете легко проверить результаты «побочных эффектов».
Например,Этот нижеметод会根据输入修изменятьчастный成员переменнаяhashCache
:
class Demo {
private Map<String, Integer> hashCache = mapOf();
public void updateCache(String domain, String key) {
String cacheKey = domain + "::" + key;
Integer num = hashCache.get(cacheKey);
hashCache.put(cacheKey, count == null ? initHash(key) : nextHash(num, key));
}
... // Другие методы опущены
}
Чтобы протестировать этот метод, вы можете использовать TestableMock, чтобы напрямую прочитать значение частной переменной-члена и проверить результат:
@EnablePrivateAccess // Включить функцию доступа к частным участникам TestableMock
class DemoTest {
private Demo demo = new Demo();
@Test
public void testSaveToCache() {
Integer firstVal = demo.initHash("hello"); // доступ к частным методам
Integer nextVal = demo.nextHash(firstVal, "hello"); // доступ к частным методам
demo.saveToCache("demo", "hello");
assertEquals(firstVal, demo.hashCache.get("demo::hello")); // читать личноепеременная
demo.saveToCache("demo", "hello");
assertEquals(nextVal, demo.hashCache.get("demo::hello")); // читать личноепеременная
}
}
Например, следующий метод выводит информацию на консоль на основе ввода:
class Demo {
public void recordAction(Action action) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss ");
String timeStamp = df.format(new Date());
System.out.println(timeStamp + "[" + action.getType() + "] " + action.getTarget());
}
}
Чтобы протестировать этот метод,можно использоватьTestableMockбыстрыйMockТерятьSystem.out.println
метод。существоватьMockметодтеловнутриможно продолжать Выполнить исходный вызов(Это эквивалентно не влиянию на оригинал.метод Функция,Используется только для записи разговоров),Вы также можете оставить это поле пустым (что эквивалентно удалению побочных эффектов исходного метода).
После выполнения тестируемого метода типа void,использоватьInvokeVerifier.verify()
Убедитесь, что входящее содержимое печати соответствует ожиданиям.:
class DemoTest {
private Demo demo = new Demo();
// Перехват вызовов `System.out.println`
@MockMethod
public void println(PrintStream ps, String msg) {
// Выполнить исходный вызов
ps.println(msg);
}
@Test
public void testRecordAction() {
Action action = new Action("click", ":download");
demo.recordAction();
// Убедитесь, что вызывается метод Mock `println` и переданные параметры соответствуют ожиданиям.
verify("println").with(matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2} \\[click\\] :download"));
}
}
Адрес с открытым исходным кодом: https://gitee.com/mirrors/TestableMock.
Следите за публичной учетной записью WeChat Тджун , ответить после подписки mock Получите документацию по использованию инструмента-макета.
Как получить: 1. Отсканируйте QR-код ниже 2. сосредоточиться а затем ответьте «mock», чтобы скачать.
Почему фрагменты кода на StackOverflow разрушат ваш проект?
Я слышал, что другого брата избили за использование ГГГГ-ММ-дд...
FFmpeg отмечает свое 20-летие! В одиночку поддержите бесчисленное количество игроков по всему миру!
﹀
﹀
﹀
Углубленное общение
технология + общество
Рабочее место + Предпринимательство