()
+
+/**
+ * Argument that is either null or of the given type.
+ *
+ *
+ * See examples in javadoc for {@link ArgumentMatchers} class
+ *
+ *
+ * @param clazz Type to avoid casting
+ * @return null.
+ */
+fun nullable(clazz: Class?): T {
+ AdditionalMatchers.or(ArgumentMatchers.isNull(), ArgumentMatchers.isA(clazz))
+ return Primitives.defaultValue(clazz) as T
+}
+
+
+/**
+ * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
+ * when null is returned.
+ */
+fun capture(argumentCaptor: ArgumentCaptor): T = argumentCaptor.capture()
+
+
+/**
+ * Helper function for creating an argumentCaptor in kotlin.
+ */
+inline fun argumentCaptor(): ArgumentCaptor =
+ ArgumentCaptor.forClass(T::class.java)
\ No newline at end of file
diff --git a/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/ErrorResponseMock.kt b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/ErrorResponseMock.kt
new file mode 100644
index 000000000..09dcc73fa
--- /dev/null
+++ b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/ErrorResponseMock.kt
@@ -0,0 +1,10 @@
+package br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks
+
+import br.com.silas.domain.ErrorResponse
+
+class ErrorResponseMock {
+ companion object {
+ fun getErrorResponseIsEmpty() = ErrorResponse(0,"")
+ fun getErrorResponseIsNotEmpty() = ErrorResponse(0,"Teste")
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/StatementsMock.kt b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/StatementsMock.kt
new file mode 100644
index 000000000..0e77423f2
--- /dev/null
+++ b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/StatementsMock.kt
@@ -0,0 +1,10 @@
+package br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks
+
+import br.com.silas.domain.statements.Statements
+
+class StatementsMock {
+ companion object {
+ fun getListStatements() =
+ listOf(Statements("Pagamento", "Conta de Luz", "2018-08-15", 745.03))
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/UserMock.kt b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/UserMock.kt
new file mode 100644
index 000000000..8faf9bc37
--- /dev/null
+++ b/presentation/src/test/java/br/com/silas/testeandroidv2/mocks/UserMock.kt
@@ -0,0 +1,9 @@
+package br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks
+
+import br.com.silas.domain.user.User
+
+class UserMock {
+ companion object {
+ fun getUserMock() = User(1, "Jose da Silva Teste", "2050", "012314564", 3.3445)
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/LoginViewModelTest.kt b/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/LoginViewModelTest.kt
new file mode 100644
index 000000000..c7e39f51f
--- /dev/null
+++ b/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/LoginViewModelTest.kt
@@ -0,0 +1,109 @@
+package br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.viewModels
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import br.com.silas.domain.user.GetUserInteractor
+import br.com.silas.domain.user.LoginInteractor
+import br.com.silas.domain.user.SaveUserInteractor
+import br.com.silas.domain.user.User
+import br.com.silas.testeandroidv2.any
+import br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks.ErrorResponseMock
+import br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks.UserMock
+import br.com.silas.testeandroidv2.ui.user.LoginViewModel
+import io.reactivex.rxjava3.core.Completable
+import io.reactivex.rxjava3.core.Single
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.core.Is.`is`
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+class LoginViewModelTest {
+ @Mock
+ private lateinit var loginInteractor: LoginInteractor
+ @Mock
+ private lateinit var saveUserInteractor: SaveUserInteractor
+
+ @Mock
+ lateinit var getUserInteractor: GetUserInteractor
+
+ lateinit var userMock: User
+ lateinit var loginViewModel: LoginViewModel
+
+ @get:Rule
+ var rule: TestRule = InstantTaskExecutorRule()
+
+ @Before
+ @Throws(Exception::class)
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ userMock = UserMock.getUserMock()
+ loginViewModel = LoginViewModel(loginInteractor, getUserInteractor, saveUserInteractor)
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun `when fetch user is successful should be return an user`() {
+ val loginError = ErrorResponseMock.getErrorResponseIsEmpty()
+ val pairResult = Pair(userMock, loginError)
+
+ `when`(loginInteractor.execute(any())).thenReturn(Single.just(pairResult))
+ loginViewModel.fetUser("teste@teste.com", "Teste#01")
+
+ assertThat(loginViewModel.user.value, `is`(pairResult.first))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun `when fetch user is unsuccessful should be return a message of error`() {
+ val loginError = ErrorResponseMock.getErrorResponseIsNotEmpty()
+ val pairResult = Pair(userMock, loginError)
+
+ `when`(loginInteractor.execute(any())).thenReturn(Single.just(pairResult))
+ loginViewModel.fetUser("teste@teste.com", "Teste#01")
+
+ assertThat(loginViewModel.errorLogin.value, `is`(pairResult.second))
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun `when fetch user is fail should be return an exception`() {
+ val exception = Exception()
+ `when`(loginInteractor.execute(any())).thenReturn(Single.error(exception))
+ loginViewModel.fetUser("user", "123")
+
+ assertThat(loginViewModel.error.value, `is`(exception))
+ }
+
+ @Test
+ fun `When fetch for user logged, should be return an user`() {
+ val user = UserMock.getUserMock()
+ `when`(getUserInteractor.execute()).thenReturn(user)
+ loginViewModel.getLastLoggedUser()
+
+ assertThat(loginViewModel.lastUserLogged.value, `is`(user))
+ }
+
+ @Test
+ fun `When save user in preferences is success should be return true`() {
+ val user = UserMock.getUserMock()
+ `when`(saveUserInteractor.execute(any())).thenReturn(Completable.complete())
+ loginViewModel.saveUser(user)
+
+ assertThat(loginViewModel.userSaved.value, `is`(true))
+ }
+
+ @Test
+ fun `When save user in preferences is unsuccessful should be return an exception`() {
+ val user = UserMock.getUserMock()
+ val exception = Exception()
+ `when`(saveUserInteractor.execute(any())).thenReturn(Completable.error(exception))
+ loginViewModel.saveUser(user)
+
+ assertThat(loginViewModel.userSaved.value, `is`(false))
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/StatementsViewModelTest.kt b/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/StatementsViewModelTest.kt
new file mode 100644
index 000000000..3a157fb66
--- /dev/null
+++ b/presentation/src/test/java/br/com/silas/testeandroidv2/viewModels/StatementsViewModelTest.kt
@@ -0,0 +1,63 @@
+package br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.viewModels
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import br.com.silas.domain.statements.StatementsInteractor
+import br.com.silas.testeandroidv2.any
+import br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks.ErrorResponseMock
+import br.com.silas.testeandroidv2.br.com.silas.testeandroidv2.mocks.StatementsMock
+import br.com.silas.testeandroidv2.ui.statements.StatementsViewModel
+import io.reactivex.rxjava3.core.Maybe
+import io.reactivex.rxjava3.core.Single
+import org.hamcrest.CoreMatchers.`is`
+import org.hamcrest.MatcherAssert.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestRule
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+import org.mockito.junit.MockitoJUnitRunner
+
+@RunWith(MockitoJUnitRunner::class)
+class StatementsViewModelTest {
+
+ @Mock
+ lateinit var statementsInteractor: StatementsInteractor
+
+ lateinit var statementsViewModel: StatementsViewModel
+
+ @get:Rule
+ var rule: TestRule = InstantTaskExecutorRule()
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ statementsViewModel = StatementsViewModel(statementsInteractor)
+ }
+
+ @Test
+ fun `When fetch statements is successful should be return a list of statements`() {
+ val statementsList = StatementsMock.getListStatements()
+ val statementsError = ErrorResponseMock.getErrorResponseIsEmpty()
+ val pairResponse = Pair(statementsError, statementsList)
+
+ `when`(statementsInteractor.execute(any())).thenReturn(Single.just(pairResponse))
+ statementsViewModel.loadStatements(152)
+
+ assertThat(statementsViewModel.result.value, `is`(pairResponse.second))
+ }
+
+ @Test
+ fun `When fetch statements is unsuccessful should be return an error response`() {
+ val statementsList = StatementsMock.getListStatements()
+ val statementsError = ErrorResponseMock.getErrorResponseIsNotEmpty()
+ val pairResponse = Pair(statementsError, statementsList)
+
+ `when`(statementsInteractor.execute(any())).thenReturn(Single.just(pairResponse))
+ statementsViewModel.loadStatements(152)
+
+ assertThat(statementsViewModel.errorStatements.value, `is`(pairResponse.first))
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 000000000..1f270603b
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,4 @@
+include ':data'
+include ':domain'
+include ':presentation'
+rootProject.name = "TesteAndroidv2"
\ No newline at end of file