https://kotlinlang.org logo
Title
p

Patrick Ramsey

06/04/2021, 7:32 PM
I just added a dependency which pulled in slf4j and slf4j-android into my kotlin android project. It looks like JvmMockKGateway.Companion logs from its init {} block, and if slf4j is present, it uses slf4j. And with the slf4j-android binding present, slf4j will call into android.util.Log, which will raise an assertion error if it’s called from a unit test, when unmocked, resulting in an exception, resulting in a NoClassDefFoundError for JvmMockKGateway.
e

ephemient

06/05/2021, 7:20 PM
assuming you're in an Android unit test, I don't see why this would result in NoClassDefFoundError - it should be running with a stub Android API
(which still throws, but can be silence with
android { testOptions { unitTests.isReturnDefaultValues = true } }
)
p

Patrick Ramsey

06/08/2021, 10:23 PM
So, I’ve been trying to avoid turning on isReturnDefaultValues, because their own documentation warns you away from it
@ephemient but as you point out, the android api throws. Which unfortunately, it throws from JvmMockKGateway.Companion’s init { } block
which means that the class encounters an exception during initialization, which in turn results in a NoClassDefFoundException.
I’m not sure if this amounts to a bug in mockk --- if it is, I’m happy to go report it!
(that it logs from there, I mean)
Apologies for the delayed response.
e

ephemient

06/08/2021, 10:26 PM
I wouldn't consider it mockk bug - seems like anything that logs would have problems in this setup.
p

Patrick Ramsey

06/08/2021, 10:27 PM
yeah. but what I mean is, it seems unsafe for mockk to be logging from its class initializer (isn’t it?)
given that some log implementations will throw exceptions
which the normal way to get around is to mock them.
at least, unsafe for it to be logging via slf4j.
at the very least it seems like it should have a try/except around the log statement and/or a logging fallback mode
because there’s no way for people to using mockk to work around it, since by the time it makes it to the caller it’s a NoClassDefFoundException
e

ephemient

06/08/2021, 10:30 PM
I don't agree - loggers should generally not throw. if an exception is recoverable it should be handled inside the logger and if it is not recoverable then the application should not continue
ideally you either configure slf4j not to use -android in your unit test, or configure the unit test to allow the android logger to work
p

Patrick Ramsey

06/08/2021, 10:32 PM
I agree that they shouldn’t
but android’s does!
when run in a test environment, which is specifically when mockk is used.
and unfortunately, it’s an external dependency that brings in -android
so we have no control over it
e

ephemient

06/08/2021, 10:33 PM
any dependency that brings in a specific slf4j binding is broken :(
p

Patrick Ramsey

06/08/2021, 10:33 PM
100% agree
and we’ve reported it to them too
but can’t always rely on external vendors being well-behaved 😕
I may report it as an issue anyway if only to have the discussion (unless you think it’s a bad idea)
because it feels like, yes, this is a misbehaving dependency, but the failure mode that results seems far more catastrophic than it has to be
e

ephemient

06/08/2021, 10:36 PM
IMO it isn't a configuration that MockK should be expected to handle, and you should still have other workarounds
using https://github.com/ljacomet/logging-capabilities to force it to a different slf4j binding, for example
p

Patrick Ramsey

06/08/2021, 10:36 PM
Ahhh --- thanks for pointing me in that direction!
hadn’t started digging into ways to override the slf4j binding yet
which I definitely should have done before coming here 😐
thanks again. I’ll check it and similar tools out.
and sorry for the noise!