Conversation
to handle converting to ICU Calendar
| private val Iso8601Locale by lazy(LazyThreadSafetyMode.NONE) { | ||
| ULocale.Builder() | ||
| .setExtension('u', "ca-iso8601") | ||
| .build() | ||
| } |
There was a problem hiding this comment.
Since AndroidDateTimeConverter is an object, this ULocale instantiation was happening immediately when FormattedResources was accessed, causing the JVM test to (still) crash. Loading it lazily avoids this.
This prevents the ULocale from being instantiated at class-loading time, which would crash JVM tests due to the missing Android implementation.
7fa0ec6 to
83c9523
Compare
JakeWharton
left a comment
There was a problem hiding this comment.
Definitely not sure how I feel about this. It's basically Dispatchers.setMain which is my mortal enemy.
| @Before fun substituteDateTimeConverter() { | ||
| FormattedResources.dateTimeConverter = JvmDateTimeConverter |
There was a problem hiding this comment.
Yep. Nothing better came to mind quickly but I can stew on it a bit longer.
|
I just realized I never responded to this, so sorry about that! I think that in practice this approach probably would work fine (at least for our setup at Cash), even if we're leaking state across tests. Definitely agree that swapping out the static reference is painful though and it would be great to avoid it. We could potentially limit the API surface a bit by hiding the assignment behind a JUnit Another thing we could explore is making the resources themselves injectable. Something like: val FormattedResources = BaseFormattedResources(dateConverter = AndroidDateConverter)
class BaseFormattedResources(private val dateConverter : DateConverter<*>) {
fun my_string(date: LocalDate): FormattedResource { ... }
}People could still reference the default resources statically, but they could also pass in an instance if they need to for testing: class MyPresenter(private val formattedResources: BaseFormattedResources = FormattedResources) { ... }
class MyPresenterTest {
private val presenter = MyPresenter(BaseFormattedResources(JvmDateConverter))
}Lots of options here in terms of naming, the exact configuration, how much we encourage static use vs injecting instances, etc. |
|
Makes sense. I'll give this a try. |
Closes #230.
This implements the first solution I proposed in #230. I'm not overly attached to this approach, just wanted to prove it out.
This pulls all
android.icuimports out of generated code and into the runtime, allowing substitution of non-Android ICU dependencies in JVM unit tests.Generated code now uses a generic
DateTimeConverterinterface to format date/time parameters. The defaultAndroidDateTimeConverterimplementation instantiatesandroid.icu.util.Calendars. JVM tests can substitute aJvmDateTimeConverterinto theirFormattedResourcesobject to instantiatecom.ibm.icu.util.Calendars, avoiding the need for Robolectric to format date/time strings.