We’re having some difficulties with thrown exceptions from the shared code that we handle in the iOS...
e

Eirik Vale Aase

almost 4 years ago
We’re having some difficulties with thrown exceptions from the shared code that we handle in the iOS side. We annotate suspending functions in our domain/data layer with
Throws(Throwable:class)
and we log these errors to Crashlytics. Problem is, the error we get (when we cast it as an NSError) has a user info dictionary with a KotlinException entry, and it has a code of 0 and a domain of “KotlinException”. This causes all errors logged to crashlytics to be grouped under the same bucket. The Kotlin throwable has a message which looks something like this (this is formatted for readability, it’s still a string)
Exception in http request:
    Error Domain=NSURLErrorDomain Code=-1009 "The Internet connection appears to be offline."
    UserInfo={
        _kCFStreamErrorCodeKey=50,
        NSUnderlyingError=0x28035a940 {
            Error Domain=kCFErrorDomainCFNetwork Code=-1009 "(null)"
            UserInfo={
                _NSURLErrorNWPathKey=unsatisfied (No network route),
                _kCFStreamErrorCodeKey=50,
                _kCFStreamErrorDomainKey=1
            }
        },
        _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <595E528B-8F59-4D85-88EE-DD084FC43CE7>.<1>,
        _NSURLErrorRelatedURLSessionTaskErrorKey=(
            "LocalDataTask <595E528B-8F59-4D85-88EE-DD084FC43CE7>.<1>"
        ),
        NSLocalizedDescription=The Internet connection appears to be offline.,
        NSErrorFailingURLStringKey=SOME URL,
        NSErrorFailingURLKey=SOME URL,
        _kCFStreamErrorDomainKey=1
    }
I could try and parse this string, extract regex matches etc, but I was wondering if there is a better way. It seems like Kotlin packs all of the interesting stuff and concatenates their string representations and just stuffs it into the userInfo entry. I would very much have liked to get the actual error instance. How do people handle this?
👀 3
Hello, i'm trying to mock Instant but I can't seem to get it to work. My approach: ```object MockkIn...
t

tim

about 5 years ago
Hello, i'm trying to mock Instant but I can't seem to get it to work. My approach:
object MockkInstant {
    var value: Instant = Instant.now()

    fun mock() {
        mockkStatic(Instant::class)

        every {
            Instant.now()
        } answers {
            value.minusMillis(0) // line 22 from stack trace below
        }
    }

    fun clear() {
        clearStaticMockk(Instant::class)
    }

    fun step(duration: Duration = 1.seconds) {
        value = value.add(duration) // extension function defined elsewhere
    }
}
Now in my tests i'm trying to do this:
"fixes calls to Instant.now()" {
    val a = Instant.now()
    delay(1)
    val b = Instant.now()
    a.shouldBe(b)
}
But I'm getting an error from the
answers
block:
Empty list doesn't contain element at index 0.
java.lang.IndexOutOfBoundsException: Empty list doesn't contain element at index 0.
	at kotlin.collections.EmptyList.get(Collections.kt:35)
	at kotlin.collections.EmptyList.get(Collections.kt:23)
	at io.mockk.MockKAnswerScope.getValueAny(API.kt:3834)
	at io.mockk.MockKAnswerScope.getValue(API.kt:2188)
	at io.glimpseprotocol.testing.mockk.MockkInstant$mock$2.invoke(MockkInstant.kt:22)
	at io.glimpseprotocol.testing.mockk.MockkInstant$mock$2.invoke(MockkInstant.kt:13)
	at io.mockk.MockKStubScope$answers$1.invoke(API.kt:2092)
	at io.mockk.MockKStubScope$answers$1.invoke(API.kt:2069)
	at io.mockk.FunctionAnswer.answer(Answers.kt:19)
...
I've seen other people using returns, but afaik that returns the same Instant object whereas I want to create a new one each time Instant.now() is called. Any suggestions?