Skip to content

Instantly share code, notes, and snippets.

@rozkminiacz
Created March 12, 2018 08:59
Show Gist options
  • Save rozkminiacz/0fa314ba326fa1018ae53075bfd6eb06 to your computer and use it in GitHub Desktop.
Save rozkminiacz/0fa314ba326fa1018ae53075bfd6eb06 to your computer and use it in GitHub Desktop.
Model View Presenter Writing Spek Specification - gists for blog post
dependencies {
(...)
testImplementation unitTestDependencies.values()
testImplementation spekDependencies.values()
testImplementation kotlinTestDependencies.values()
}
interface PeopleListContract {
interface View {
fun addPeople(people: List<Person>)
fun showError(throwable: Throwable = Throwable())
fun showLoading()
fun hideLoading()
}
interface Presenter {
fun attach(view: View)
fun detach()
}
}
class PeopleListPresenter(private val repository: Repository<Person>) : PeopleListContract.Presenter {
var view: PeopleListContract.View? = null
override fun attach(view: PeopleListContract.View) {
this.view = view
loadPeople()
}
private fun loadPeople() {
repository.getAll()
.doOnSubscribe { view?.showLoading() }
.doOnError {
view?.apply {
showError(it)
hideLoading()
}
}
.doOnSuccess {
view?.apply {
addPeople(it)
hideLoading()
}
}
.subscribe()
}
}
class PeopleListPresenter(val repository: Repository<Person>) : PeopleListContract.Presenter {
var view: PeopleListContract.View? = null
override fun attach(view: PeopleListContract.View) {
this.view = view
}
override fun detach() {
this.view = null
}
}
val presenter = PeopleListPresenter(repository)
on("presenter attach"){
presenter.attach(view)
it("should attach view"){
assertNotNull(presenter.view)
}
it("should start loading") {
verify(view).showLoading()
}
it("should load list into view"){
verify(view).addPeople(peopleList)
}
it("should stop loading") {
verify(view).hideLoading()
}
it("should never show any error"){
verify(view, never()).showError(anyOrNull())
}
}
on("presenter detach"){
it("should detach view"){
presenter.detach()
assertNull(presenter.view)
}
}
given("no people in repository"){
val view: PeopleListContract.View = mock()
val repository : Repository<Person> = mock {
on { getAll() } doReturn Single.error(Error("no data"))
}
val presenter = PeopleListPresenter(repository)
on("presenter attach"){
presenter.attach(view)
presenterAttachStandardFlow(view, presenter){
it("should not add anything to view"){
verify(view, never()).addPeople(any())
}
it("should display error in view"){
verify(view).showError(any())
}
}
}
presenterDetachAction(presenter)
}
val peopleList : List<Person> = listOf(
Person(id = "1", firstName = "Mark", surname = "Train"),
Person(id = "2", firstName = "George", secondName = "Edward", surname = "Bicycle")
)
val repository : Repository<Person> = mock{
on { getAll() } doReturn Single.just(peopleList)
}
given("no people in repository"){
val view: PeopleListContract.View = mock()
val repository : Repository<Person> = mock {
on { getAll() } doReturn Single.error(Error("no data"))
}
val presenter = PeopleListPresenter(repository)
on("presenter attach"){
presenter.attach(view)
presenterAttachStandardFlow(view, presenter){
it("should not add anything to view"){
verify(view, never()).addPeople(any())
}
it("should display error in view"){
verify(view).showError(any())
}
}
}
}
on("presenter attach") {
presenter.attach(view)
it("should attach view") {
assertNotNull(presenter.view)
}
it("should start loading") {
verify(view).showLoading()
}
it("should load list into view") {
verify(view).addPeople(peopleList)
}
it("should stop loading") {
verify(view).hideLoading()
}
it("should never show any error") {
verify(view, never()).showError(anyOrNull())
}
}
import org.jetbrains.spek.api.Spek
import org.jetbrains.spek.api.dsl.*
import org.junit.platform.runner.JUnitPlatform
import com.nhaarman.mockito_kotlin.*
import org.junit.runner.RunWith
@RunWith(JUnitPlatform::class)
object PeopleListTest : Spek({
given("people exists in repository"){
val view: PeopleListContract.View = mock()
}
})
on("presenter attach") {
presenter.attach(view)
presenterAttachStandardFlow(view, presenter) {
it("should add people to view") {
verify(view).addPeople(peopleList)
}
it("should never show error") {
verify(view, never()).showError(anyOrNull())
}
}
}
fun ActionBody.presenterAttachStandardFlow(
view: PeopleListContract.View,
presenter: PeopleListPresenter,
additionalTestBlock: () -> Unit) {
it("should attach view") {
Assert.assertNotNull(presenter.view)
}
it("should start loading") {
verify(view).showLoading()
}
additionalTestBlock.invoke()
it("should stop loading") {
verify(view).hideLoading()
}
}
fun SpecBody.detachPresenterAction(presenter: PeopleListPresenter) {
on("presenter detach") {
presenter.detach()
it("should detach view") {
Assert.assertNull(presenter.view)
}
}
}
interface Repository<in T>{
fun getAll() : Single<List<T>>
fun getOne(id : String) : Single<T>
fun create(t : T)
}
on("presenter detach"){
presenter.detach()
it("should dispose observables"){
//
}
}
ext {
def JunitVersion = '4.12'
def KotlinMockitoVersion = '1.5.0'
def SpekVersion = "1.1.5"
unitTestDependencies = [
junit : "junit:junit:${JunitVersion}",
]
kotlinTestDependencies = [
kotlinMockito: "com.nhaarman:mockito-kotlin:${KotlinMockitoVersion}",
]
spekDependencies = [
spekApi: "org.jetbrains.spek:spek-api:${SpekVersion}",
platformEngine: "org.jetbrains.spek:spek-junit-platform-engine:${SpekVersion}",
junitPlatformRunner: "org.junit.platform:junit-platform-runner:1.0.0"
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment