https://kotlinlang.org logo
Title
z

zak.taccardi

09/16/2019, 3:03 PM
has anyone heard of a library that provides a delegated property for constructing things in JUnit’s setUp phase automatically? instead of:
private lateinit var dog: Dog

@Before fun setUp() {
  dog = Dog()
}
there would be:
private val dog by before { Dog() } // constructs `Dog` instance once per test
seems like this could be pretty useful?
w

wasyl

09/16/2019, 3:05 PM
You’d need to hook into test lifecycle somehow. It’s what rules are for, so such delegated property would still need to have @Rule annotation and would have to implement a Rule, I think
s

streetsofboston

09/16/2019, 3:15 PM
Why not just
class MyDogTest {
    private val dog = Dog()
    ...
    @Test fun someTest() { .... dog .... }
    ...
}
? Most (if not all) unit-test-runners I know always create a brand new instance of
MyDogTest
for every unit-test function that is executed.
👆 3
p

Paul Woitaschek

09/16/2019, 3:23 PM
I also removed all my @Before functions which made my tests way clearer because now there are no lateinits any longer
w

wasyl

09/16/2019, 3:23 PM
Yep, I don’t know why I thought rule is even useful if you’re not closing the object 🤦‍♂️ In JUnit afaik there’s no difference between creating an instance inline vs @Before method: https://stackoverflow.com/a/6094143/1349855
v

Vlad

09/16/2019, 3:42 PM
A common use case for @before and instantiation that I run into is when I need to substitute my coroutine dispatcher with the test version in the
android.Viewmodel
and there is something in the init {} block that runs the coroutine or observes the flow.
w

wasyl

09/16/2019, 3:44 PM
if a property is written before an
init
block, it’s initialized first
v

Vlad

09/16/2019, 3:46 PM
Yes, but in
coroutines-test
it's the `Dispatchers::setMain`invocation that is required to set the main dispatcher... But I guess it could also be injected
w

wasyl

09/16/2019, 3:47 PM
Oh you meant the other way around! Technically in that case you can also have an
init
block before the property declaration (and another init block later if you want)
👍 1
s

streetsofboston

09/16/2019, 3:48 PM
Yup; we usually inject it. There is a
setMain
, but no such hooks such as
setDefault
or
setIO
🙂
(or use @Inject with Dagger 🙂 )
m

Mike

09/16/2019, 5:25 PM
By default, JUnit Jupiter and JUnit4 create a new instance of the test for each method execution, therefore the
val dog = Dog()
is acceptable. BUT some frameworks, including JUnit Jupiter allow for a change to that lifecycle so the test is only instantiated ONCE, and all test methods are then run. https://junit.org/junit5/docs/current/user-guide/#writing-tests-test-instance-lifecycle
👍 1