Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SpekでUnitTestを書こう / unit-test-with-spek

moriiimo
February 08, 2019

SpekでUnitTestを書こう / unit-test-with-spek

moriiimo

February 08, 2019
Tweet

More Decks by moriiimo

Other Decks in Technology

Transcript

  1. 5PEP$MBTT class Todo(val id: Int) { constructor(id: Int, label: String,

    complete: Boolean, deadline: Long) : this(id) { this.label = label this.complete = complete this.deadline = deadline } var label: String = "" private set var complete: Boolean = false private set var deadline: Long = System.currentTimeMillis() private set }
  2. 5PEP$MBTT fun checkComplete() { complete = true } fun unCheckComplete()

    { complete = false } ऴྃঢ়ଶͷ มߋ͕Ͱ͖ͨΓʜ
  3. 5PEP$MBTT fun addDayToDeadline(numOfDays: Int) { changeDeadline(numOfDays) } fun reduceDayToDeadline(numOfDays: Int)

    { changeDeadline(-numOfDays) } private fun changeDeadline(numOfDays: Int) { deadline = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = deadline add(Calendar.DATE, numOfDays) }.timeInMillis } ظݶͷมߋ͕ Ͱ͖ͨΓ͠·͢
  4. +6OJU5PEP5FTU class TodoTest { private val now = System.currentTimeMillis() private

    lateinit var todo: Todo @Before fun setup() { todo = Todo(id = 1, label = "Write Unit Test with Spek", complete = false, deadline = now ) } @Test fun changeCompleteStatus_shouldBeTrue() { todo.checkComplete() assertTrue(todo.complete) } @Test fun changeCompleteStatus_shouldBeFalse() { todo.unCheckComplete() assertFalse(todo.complete) } @Test fun addDaysToDeadline_shouldBeThreeDaysLater() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, 3) } todo.addDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } @Test fun reduceDaysToDeadline_shouldBeThreeDaysAgo() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, -3) } todo.reduceDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } }
  5. ݟͮΒ͍ϙΠϯτ @Test fun changeCompleteStatus_shouldBeTrue() { todo.checkComplete() assertTrue(todo.complete) } @Test fun

    changeCompleteStatus_shouldBeFalse() { todo.unCheckComplete() assertFalse(todo.complete) }
  6. ݟͮΒ͍ϙΠϯτ @Test fun changeCompleteStatus_shouldBeTrue() { todo.checkComplete() assertTrue(todo.complete) } @Test fun

    changeCompleteStatus_shouldBeFalse() { todo.unCheckComplete() assertFalse(todo.complete) } @Test fun addDaysToDeadline_shouldBeThreeDaysLater() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, 3) } todo.addDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) }
  7. ݟͮΒ͍ϙΠϯτ @Test fun changeCompleteStatus_shouldBeTrue() { todo.checkComplete() assertTrue(todo.complete) } @Test fun

    changeCompleteStatus_shouldBeFalse() { todo.unCheckComplete() assertFalse(todo.complete) } @Test fun addDaysToDeadline_shouldBeThreeDaysLater() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, 3) } todo.addDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } @Test fun reduceDaysToDeadline_shouldBeThreeDaysAgo() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, -3) } todo.reduceDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } ΧςΰϥΠζɺ ֊૚ԽͰ͖ͳ͍
  8. ݟͮΒ͍ϙΠϯτ @Test fun changeFinishStatus_shouldBeTrue() { todo.markFinished() assert(todo.finished) } @Test fun

    changeFinishStatus_shouldBeFalse() { todo.markUnFinished() assert(!todo.finished) } @Test fun addDaysToDeadline_shouldBeThreeDaysLater() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, 3) } todo.addDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } @Test fun reduceDaysToDeadline_shouldBeThreeDaysAgo() { val expect = Calendar.getInstance(TimeZone.getDefault(), Locale.JAPAN).apply { timeInMillis = now add(Calendar.DATE, -3) } todo.reduceDayToDeadline(3) assertEquals(expect.timeInMillis, todo.deadline) } ࣮ߦॱং͕อূ ͞Εͳ͍
  9. 4QFL5PEP5FTU class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo Scenario("complete status") { Given("the todo is not complete") { todo = Todo( id = 1, label = "", deadline = now, complete = false ) } When("complete the todo") { todo.checkComplete() } Then("the todo is complete") { assertTrue(todo.complete) } When("return the todo to incomplete") { todo.unCheckComplete() } Then("the todo is not complete") { assertTrue(!todo.complete) } } } })
  10. ݟ΍͍͢ϙΠϯτ Scenario("complete status") { Given("the todo is not complete") {

    todo = Todo( id = 1, label = "", deadline = now, complete = false ) } When("complete the todo") { todo.checkComplete() } Then("the todo is complete") { assertTrue(todo.complete) } }
  11. ݟ΍͍͢ϙΠϯτ Scenario("complete status") { Given("the todo is not complete") {

    todo = Todo( id = 1, label = "", deadline = now, complete = false ) } When("complete the todo") { todo.checkComplete() } Then("the todo is complete") { assertTrue(todo.complete) } } ૝ఆ͕ ॻ͖΍͍͢
  12. ิ଍ Scenario("changing todo finish status") { Given("todo is not finish")

    { todo = Todo( id = 1, label = "Write Unit Test with Spek", finished = false, deadline = now ) } When("mark finish") { todo.markFinished() } Then("it should be true") { assertTrue(todo.finished) } } ૝ఆ͕ ॻ͖΍͍͢ ͪͳΈʹʜ͜ͷΑ͏ͳه๏͸(IFSLJOͱ͍͏ ςετهड़ݴޠϑΥʔϚοτ͕ݩʹͳ͍ͬͯ·͢
  13. ิ଍ Scenario("changing todo finish status") { Given("todo is not finish")

    { todo = Todo( id = 1, label = "Write Unit Test with Spek", finished = false, deadline = now ) } When("mark finish") { todo.markFinished() } Then("it should be true") { assertTrue(todo.finished) } } ૝ఆ͕ ॻ͖΍͍͢ ͪͳΈʹʜ͜ͷΑ͏ͳه๏͸(IFSLJOͱ͍͏ ςετهड़ݴޠϑΥʔϚοτ͕ݩʹͳ͍ͬͯ·͢ ػೳ50%0 γφϦΦऴྃεςʔλε͕ਖ਼͘͠มԽ͢Δ લఏ50%0ͷऴྃεςʔλε͕ະ׬ྃ ΋͠50%0ͷऴྃεςʔλεΛ׬ྃʹͨ͠Β ͳΒ͹50%0ͷऴྃεςʔλε͕׬ྃʹͳΔ ೔ຊޠͰ΋͔͚ͯɺ ॻ͘ͱ͜Μͳײ͡ʹͳΔ
  14. ݟ΍͍͢ϙΠϯτ class TodoFeature : Spek({ Feature("Todo") { Scenario(“complete status") {

    . . . ऴྃεςʔλεͷςετ } Scenario("deadline") { . . . క੾ͷςετ } Scenario(“label") { . . . ໊લͷςετ } } })
  15. ݟ΍͍͢ϙΠϯτ class TodoFeature : Spek({ Feature("Todo") { Scenario(“complete status") {

    . . . ऴྃεςʔλεͷςετ } Scenario("deadline") { . . . క੾ͷςετ } Scenario(“label") { . . . ໊લͷςετ } } }) Θ͔Γ΍͘͢Χςΰ ϥΠζͰ͖Δ
  16. class TodoFeature : Spek({ Feature("Todo") { Scenario("changing finish status") {

    . . . ऴྃεςʔλεͷςετ } Scenario("changing deadline") { . . . క੾มߋͷςετ } Scenario("changing label") { . . . ໊લมߋͷςετ } } }) ݟ΍͍͢ϙΠϯτ ࣮ߦॱং͕อূ͞ΕΔ
  17. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo } })
  18. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() val todo: Todo by lazy { Todo(id = 1, label = "Write Unit Test with Spek", complete = false, deadline = now) } } }) MB[Z΋"
  19. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo Scenario("complete status") { } } })
  20. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo Scenario("complete status") { Given(“the todo is not complete") { todo = Todo(id = 1, label = "Write Unit Test with Spek”, complete = false, deadline = now) } } } })
  21. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo Scenario("complete status") { Given(“the todo is not complete") { todo = Todo(id = 1, label = "Write Unit Test with Spek", complete = false, deadline = now) } When(“complete the todo") { todo.checkComplete() } } } })
  22. جຊͷॻ͖ํ class TodoFeature : Spek({ Feature("Todo") { val now =

    System.currentTimeMillis() lateinit var todo: Todo Scenario("complete status") { Given(“the todo is not complete") { todo = Todo(id = 1, label = "Write Unit Test with Spek", complete = false, deadline = now) } When(“complete the todo") { todo.checkComplete() } Then(“the todo is complete”) { assertTrue(todo.complete) } } } })
  23. ϧʔϧ class TodoFeature : Spek({ Feature("xxx") { Scenario("xxx") { .

    . . xxxͷςετ } Scenario("yyy") { . . . yyyͷςετ } } Feature("zzz") { Scenario("zzz") { . . . zzzͷςετ } } }) ෳ਺ͷ'FBUVSFɺ'FBUVSF಺ͷ ෳ਺ͷγφϦΦʁ
  24. ෳ਺ͷ'FBUVSFɺ'FBUVSF಺ͷ ෳ਺ͷγφϦΦʁ ϧʔϧ class TodoFeature : Spek({ Feature("xxx") { Scenario("xxx")

    { . . . xxxͷςετ } Scenario("yyy") { . . . yyyͷςετ } } Feature("zzz") { Scenario("zzz") { . . . zzzͷςετ } } }) "
  25. ϧʔϧ class TodoFeature : Spek({ Feature(“xxx") { Scenario("xxx") { Scenario(“yyy")

    { Given("xxx") { Given(“yyy”) { } } } } } }) γφϦΦ΍(JWFO8IFO 5IFOͷωετʁ
  26. γφϦΦ΍(JWFO8IFO 5IFOͷωετʁ ϧʔϧ class TodoFeature : Spek({ Feature(“xxx") { Scenario("xxx")

    { Scenario(“yyy") { Given("xxx") { Given(“yyy”) { } } } } } }) #
  27. @Synonym(SynonymType.GROUP, prefix = "Feature: ") @Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0)) fun GroupBody.Feature(description: String,

    body: FeatureBody.() -> Unit) { group("Feature: $description", defaultCachingMode = CachingMode.GROUP) { body(FeatureBody(this)) } }
  28. @Synonym(SynonymType.GROUP, prefix = "Feature: ") @Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0)) fun GroupBody.Feature(description: String,

    body: FeatureBody.() -> Unit) { group("Feature: $description", defaultCachingMode = CachingMode.GROUP) { body(FeatureBody(this)) } } ͜Ε
  29. @Synonym(SynonymType.GROUP, prefix = "Feature: ") @Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0)) fun GroupBody.Feature(description: String,

    body: FeatureBody.() -> Unit) { group("Feature: $description", defaultCachingMode = CachingMode.GROUP) { body(FeatureBody(this)) } } @SpekDsl class FeatureBody(val delegate: GroupBody): LifecycleAware by delegate { @Synonym(SynonymType.GROUP, prefix = "Scenario: ") @Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0)) fun Scenario(description: String, body: ScenarioBody.() -> Unit) { delegate.group("Scenario: $description”, defaultCachingMode = CachingMode.SCOPE, preserveExecutionOrder = true) { body(ScenarioBody(this)) } } }
  30. @SpekDsl class ScenarioBody(val delegate: GroupBody): LifecycleAware by delegate { fun

    Given(description: String, body: TestBody.() -> Unit) { delegate.test("Given: $description", body = body) } fun When(description: String, body: TestBody.() -> Unit) { delegate.test("When: $description", body = body) } fun Then(description: String, body: TestBody.() -> Unit) { delegate.test("Then: $description", body = body) } fun And(description: String, body: TestBody.() -> Unit) { delegate.test("And: $description", body = body) } }
  31. @SpekDsl class ScenarioBody(val delegate: GroupBody): LifecycleAware by delegate { fun

    Given(description: String, body: TestBody.() -> Unit) { delegate.test("Given: $description", body = body) } fun When(description: String, body: TestBody.() -> Unit) { delegate.test("When: $description", body = body) } fun Then(description: String, body: TestBody.() -> Unit) { delegate.test("Then: $description", body = body) } fun And(description: String, body: TestBody.() -> Unit) { delegate.test("And: $description", body = body) } }
  32. @SpekDsl class ScenarioBody(val delegate: GroupBody): LifecycleAware by delegate { fun

    Given(description: String, body: TestBody.() -> Unit) { delegate.test("Given: $description", body = body) } fun When(description: String, body: TestBody.() -> Unit) { delegate.test("When: $description", body = body) } fun Then(description: String, body: TestBody.() -> Unit) { delegate.test("Then: $description", body = body) } fun And(description: String, body: TestBody.() -> Unit) { delegate.test("And: $description", body = body) } } શ෦ಉ͡ʁ
  33. class TodoFeature : Spek({ Feature("Todo") { val now = System.currentTimeMillis()

    lateinit var todo: Todo Scenario("complete status") { Then(“the todo is not complete") { todo = Todo(id = 1, label = "Write Unit Test with Spek", complete = false, deadline = now) } Then(“complete the todo") { todo.checkComplete() } Then(“the todo is complete”) { assertTrue(todo.complete) } } } }) ͭ·Γ ͜ΕͰ΋0,
  34. class TodoFeature : Spek({ Feature("Todo") { val now = System.currentTimeMillis()

    lateinit var todo: Todo Scenario("changing todo finish status") { Then("todo is not finished ") { todo = Todo(id = 1, label = "Write Unit Test with Spek", finished = false, deadline = now) } Then("mark finish") { todo.markFinished() } Then("it should be true") { assertTrue(todo.finished) } } } }) ॱ൪͸ อূ͞Ε͍ͯΔ @SpekDsl class FeatureBody(val delegate: GroupBody): LifecycleAware by delegate { @Synonym(SynonymType.GROUP, prefix = "Scenario: ") @Descriptions(Description(DescriptionLocation.VALUE_PARAMETER, 0)) fun Scenario(description: String, body: ScenarioBody.() -> Unit) { delegate.group("Scenario: $description”, defaultCachingMode = CachingMode.SCOPE, preserveExecutionOrder = true) { body(ScenarioBody(this)) } } }
  35. -JWF%BUB+6OJU class InstantTaskExecutorRule : TestWatcher() { protected fun starting(description: Description)

    { super.starting(description) ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() { override fun executeOnDiskIO(runnable: Runnable) { runnable.run() } override fun postToMainThread(runnable: Runnable) { runnable.run() } override fun isMainThread(): Boolean { return true } }) } protected fun finished(description: Description) { super.finished(description) ArchTaskExecutor.getInstance().setDelegate(null) } }
  36. -JWF%BUB+6OJU class InstantTaskExecutorRule : TestWatcher() { protected fun starting(description: Description)

    { super.starting(description) ArchTaskExecutor.getInstance().setDelegate(object : TaskExecutor() { override fun executeOnDiskIO(runnable: Runnable) { runnable.run() } override fun postToMainThread(runnable: Runnable) { runnable.run() } override fun isMainThread(): Boolean { return true } }) } protected fun finished(description: Description) { super.finished(description) ArchTaskExecutor.getInstance().setDelegate(null) } } UFTU*NQMFNFOUBUJPOlBOESPJEBSDIDPSFDPSFUFTUJOH7&34*0/
  37. -JWF%BUB+6OJU fun GroupBody.useLiveData() { androidx.arch.core.executor.ArchTaskExecutor.getInstance().setDelega te(object : TaskExecutor() { override

    fun executeOnDiskIO(runnable: Runnable) { runnable.run() } override fun isMainThread(): Boolean { return true } override fun postToMainThread(runnable: Runnable) { runnable.run() } }) } 4QFL&YUFOUJPOLUΛ ࡞੒
  38. -JWF%BUB4QFL class TodoListViewModelSpec : Spek({ useLiveData() val application: Application by

    lazy { Mockito.mock(Application::class.java) } val todoListViewModel: TodoListViewModel by lazy { TodoListViewModel( application, Schedulers.trampoline() ) } val observer = mock<Observer<String>>() lateinit var filterWord: String Feature("TodoViewModel") { Scenario("TodoͷҰཡϑΟϧλʔ͢ΔͱLiveDataʹ৽͍͠஋͕ೖΔ") { Given("LiveData͕ΞΫςΟϒʹͳΔ") { todoListViewModel.wordLiveData.observeForever(observer) } When("ViewModelͷϑΟϧλʔϝιουΛ࣮ߦ͢Δ") { filterWord = "Spek" todoListViewModel.filter(filterWord) } Then("LiveDataͷvalue͕SpekʹͳΔ") { Mockito.verify(observer).onChanged(filterWord) } } } }) 7JFX.PEFMͷ࣋ͭ -JWF%BUBͷ஋͕ มߋ͞Ε͔ͨΛݟΔςετ
  39. -JWF%BUB4QFL val observer = mock<Observer<String>>() lateinit var filterWord: String Feature("TodoViewModel")

    { Scenario("TodoͷҰཡϑΟϧλʔ͢ΔͱLiveDataʹ৽͍͠஋͕ೖΔ") { Given("LiveData͕ΞΫςΟϒʹͳΔ") { todoListViewModel.wordLiveData.observeForever(observer) } When("ViewModelͷϑΟϧλʔϝιουΛ࣮ߦ͢Δ") { filterWord = "Spek" todoListViewModel.filter(filterWord) } Then("LiveDataͷvalue͕SpekʹͳΔ") { Mockito.verify(observer).onChanged(filterWord) } } } 0CTFSWFSͷ ϞοΫ࡞੒
  40. -JWF%BUB4QFL val observer = mock<Observer<String>>() lateinit var filterWord: String Feature("TodoViewModel")

    { Scenario("TodoͷҰཡϑΟϧλʔ͢ΔͱLiveDataʹ৽͍͠஋͕ೖΔ") { Given("LiveData͕ΞΫςΟϒʹͳΔ") { todoListViewModel.wordLiveData.observeForever(observer) } When("ViewModelͷϑΟϧλʔϝιουΛ࣮ߦ͢Δ") { filterWord = "Spek" todoListViewModel.filter(filterWord) } Then("LiveDataͷvalue͕SpekʹͳΔ") { Mockito.verify(observer).onChanged(filterWord) } } } 0CTFSWFΛ ։࢝͢Δ
  41. -JWF%BUB4QFL val observer = mock<Observer<String>>() lateinit var filterWord: String Feature("TodoViewModel")

    { Scenario("TodoͷҰཡϑΟϧλʔ͢ΔͱLiveDataʹ৽͍͠஋͕ೖΔ") { Given("LiveData͕ΞΫςΟϒʹͳΔ") { todoListViewModel.wordLiveData.observeForever(observer) } When("ViewModelͷϑΟϧλʔϝιουΛ࣮ߦ͢Δ") { filterWord = "Spek" todoListViewModel.filter(filterWord) } Then("LiveDataͷvalue͕SpekʹͳΔ") { Mockito.verify(observer).onChanged(filterWord) } } } 0CTFSWFSͷ PO$IBOHFE͕ ݺ͹Ε͔ͨνΣοΫ
  42. 3PPN3PCPMFDUSJD @RunWith(RobolectricTestRunner::class) @Config(sdk = [O_MR1]) class TodoDataBaseTest { private lateinit

    var database: TodoDatabase @Before fun openDatabase() { database = Room .inMemoryDatabaseBuilder( InstrumentationRegistry.getInstrumentation().targetContext, TodoDatabase::class.java ).allowMainThreadQueries() .build() } @After fun closeDatabase() { database.close() } @Test @Throws(Exception::class) fun insert() { assertThat(database.todoDao().count(), `is`(0)) val list = listOf( TodoEntity( name = "Robolectric࢖͏", category = 1 ), TodoEntity( name = "JUnit࢖͏", category = 1 ) ) database.todoDao().upsertAll(list) assertThat(database.todoDao().count(), `is`(2)) } }
  43. 3PPN3PCPMFDUSJD @Before fun openDatabase() { database = Room .inMemoryDatabaseBuilder( InstrumentationRegistry

    .getInstrumentation() .targetContext, TodoDatabase::class.java ).allowMainThreadQueries() .build() }
  44. 3PPN3PCPMFDUSJD @Before fun openDatabase() { database = Room .inMemoryDatabaseBuilder( InstrumentationRegistry

    .getInstrumentation() .targetContext, TodoDatabase::class.java ).allowMainThreadQueries() .build() } ίϯςΩετ͕ ͔ͭ͑Δ
  45. 3PPN3PCPMFDUSJD @Before fun openDatabase() { database = Room .inMemoryDatabaseBuilder( InstrumentationRegistry

    .getInstrumentation() .targetContext, TodoDatabase::class.java ).allowMainThreadQueries() .build() }
  46. 3PPN4QFL class TodoDaoSpec : Spek({ useLiveData() val context: Context by

    lazy { Mockito.mock(Context::class.java) } val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() } Feature("TodoDao") { lateinit var result: Single<Int> Scenario("TodoDatabase") { Given("two todos have already been registered") { val todoList = listOf( TodoEntity(name = "SpekͰUnitTestΛॻ͘", finished = false, deadline = 1L), TodoEntity(name = "JUnitͰUnitTestΛॻ͘", finished = false, deadline = 1L) ) todoDatabase.todoDao().upsertAll(todoList) } When("count todo") { result = todoDatabase.todoDao().count() } Then("it should be 2") { result.test().await().assertValue(2) } } } })
  47. 3PPN4QFL useLiveData() val context: Context by lazy { Mockito.mock(Context::class.java) }

    val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() }
  48. 3PPN4QFL useLiveData() val context: Context by lazy { Mockito.mock(Context::class.java) }

    val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() } +%#$ͷϔϧύʔ Λࢦఆ͢Δ
  49. 3PPN4QFL useLiveData() val context: Context by lazy { Mockito.mock(Context::class.java) }

    val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() } ϝΠϯεϨουͷ ֬ೝΛऔΔ
  50. 3PPN4QFL useLiveData() val context: Context by lazy { Mockito.mock(Context::class.java) }

    val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() }
  51. 3PPN4QFL useLiveData() val context: Context by lazy { Mockito.mock(Context::class.java) }

    val todoDatabase: TodoDatabase by lazy { Room.inMemoryDatabaseBuilder( context, TodoDatabase::class.java ).allowMainThreadQueries() .openHelperFactory(JdbcSQLiteOpenHelperFactory()) .build() } ίϯςΩετ͸ ୅༻Λ༻ҙ
  52. 3PPN4QFL Scenario("TodoDatabase") { lateinit var result: Single<Int> Given("two todos have

    already been registered") { val todoList = listOf( TodoEntity(name = "SpekͰUnitTestΛॻ͘", complete = false, deadline = 1L), TodoEntity(name = "JUnitͰUnitTestΛॻ͘", complete = false, deadline = 1L) ) todoDatabase.todoDao().upsertAll(todoList) } When("count todo") { result = todoDatabase.todoDao().count() } Then("it should be 2") { result.test().await().assertValue(2) } } ͍͖ͳΓͷ3Y