-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle date/time conversion in runtime #258
base: main
Are you sure you want to change the base?
Conversation
to handle converting to ICU Calendar
plugin/src/main/java/app/cash/paraphrase/plugin/ResourceWriter.kt
Outdated
Show resolved
Hide resolved
private val Iso8601Locale by lazy(LazyThreadSafetyMode.NONE) { | ||
ULocale.Builder() | ||
.setExtension('u', "ca-iso8601") | ||
.build() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
sample/library/src/test/kotlin/app/cash/paraphrase/sample/library/JvmDateTimeConverter.kt
Show resolved
Hide resolved
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely not sure how I feel about this. It's basically Dispatchers.setMain
which is my mortal enemy.
plugin/src/main/java/app/cash/paraphrase/plugin/ResourceWriter.kt
Outdated
Show resolved
Hide resolved
@Before fun substituteDateTimeConverter() { | ||
FormattedResources.dateTimeConverter = JvmDateTimeConverter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Painful 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep. Nothing better came to mind quickly but I can stew on it a bit longer.
sample/library/src/test/kotlin/app/cash/paraphrase/sample/library/JvmDateTimeConverter.kt
Show resolved
Hide resolved
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.icu
imports 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
DateTimeConverter
interface to format date/time parameters. The defaultAndroidDateTimeConverter
implementation instantiatesandroid.icu.util.Calendar
s. JVM tests can substitute aJvmDateTimeConverter
into theirFormattedResources
object to instantiatecom.ibm.icu.util.Calendar
s, avoiding the need for Robolectric to format date/time strings.