#unit-testing #object #kotlin #tdd
#модульное тестирование #объект #kotlin #tdd
Вопрос:
Учитывая логику TDD и пытаясь понять, как писать модульные тесты, у меня возникли проблемы с объектом Kotlin. Тест пройден, но я не уверен, действительно ли это правильный тест. Я пытаюсь убедиться, что вызывается метод Logger.i () и что он сохраняется в базе данных. Но на данный момент я застрял только на его вызываемой части.
Мой объект
object Logger {
fun i(tag: String, msg: String, tr: Throwable? = null): Int {
insertIntoLogDatabase(createLogModel("i", tag, msg, tr))
return if (BuildConfig.DEBUG) Log.i(tag, msg, tr) else 0
}
private fun insertIntoLogDatabase(log: LogModel) {
//Insert into Log DB
logRepo.upsert(log)
}
private fun createLogModel(type: String, tag: String, msg: String, tr: Throwable?) = LogModel(0, type, tag, msg, if (tr != null) tr.message "n" tr?.stackTrace.contentToString() else null)
fun setLogRepo(logRepo: LogRepository) {
this.logRepo = logRepo
}
}
при этом я знаю, что мне нужно вызвать Logger.setLogRepo(logRemp), чтобы предоставить регистратору доступ к репозиторию (и это работает)
Я застрял в том, что пытаюсь выполнить модульное тестирование вызова метода Log.i
У меня есть это
@Mock
lateinit var log: Logger
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
Logger.setLogRepository(logRepo)
}
@Test
fun `log i failed`() {
// When
log.i("Test", "Test1")
// Then
verify(log, times(1)).i("Test", "Test1")
}
Я имею в виду, что это работает, но правильно ли это (моя интуиция подсказывает мне, что что-то не так, что я на самом деле не тестирую метод Logger.i ()
пожалуйста, сообщите.
Спасибо.
Ответ №1:
Как вы упомянули, вы должны проверить, что при регистрации данных они должны сохраняться в репозитории в нужном вам формате, и вы хотите в основном проверить, что, когда вы выполнили работу по отправке журнала в регистратор, он отправляется в репозиторий в правильном формате, и вы будете возражать против этого.
Итак, ваш тестовый пример будет выглядеть,
@Mock
lateinit var logRepo: LogRepository
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
Logger.setLogRepository(logRepo)
}
@Test
fun `when an item is logged, it gets stored in the repository`()
{
val expectedData= <valueThatShouldBeSentToRepo>
Logger.i("Test", "Test1")
verify(logRepo).upsert(expectedData)
}
Комментарии:
1. Я попробовал это, и я получаю следующие аргументы ошибки, которые отличаются! Требуется: logRepo.upsert(0: [Test] Test1 @ 2019-03-15T15:04:29.024); -> в com.mycomp.mytest.utilities.log.LogTest.logger я потерпел неудачу (LogTest.kt: 66) Фактический вызов имеет другие аргументы: logRepo.upsert(0: [Test] Test1 @ 2019-03-15T15:04:31.206);
2. В основном, потому что ожидаемые данные и Logger.i — это две разные вещи. значит, они не совпадают?
3. Вставьте свой класс LogModel, и если это не класс данных, то сделайте его классом данных
4. Это определенно класс данных 🙂
@Entity(tableName = "Logs") data class LogModel ( @NonNull @PrimaryKey(autoGenerate = true) var logID: Long = 0, @ColumnInfo(name = "type") var type: String, @ColumnInfo(name = "tag") var tag: String, @ColumnInfo(name = "msg") var msg: String, @ColumnInfo(name = "tr") var tr: String? ) { @ColumnInfo(name = "created_date") @TypeConverters(Converters::class) var createDate: LocalDateTime? = LocalDateTime.now() override fun toString(): String { return "$logID: [$tag] $msg @ $createDaten" } }
5. Поскольку для переменной CreateDate установлено время инициализации, оно будет отличаться от ожидаемого значения и фактического значения, поскольку ожидаемое значение создается первым, а фактическое значение создается после этого внутри logger. Это можно решить двумя способами: i) Исключить CreateDate из метода equals, переместив переменную CreateDate из конструктора внутрь класса, чтобы два объекта с одинаковыми данными, но с разным временем создания, были истинными.