Hey I am using mockk library in my project. I am trying to mock MutableLiveData, but it always give me null value. Can someone guide me how to do in proper way.
Suppose I have one function
var dataLiveData = MutableLiveData<Boolean>()
val currentDeviceTypeLiveData = MutableLiveData<Boolean>()
internal fun handleDataResponse() {
dataLiveData.postValue(true)
currentDeviceTypeLiveData.postValue(true)
}
I am trying to test
#Test
fun `handleDataResponse - Handle connection success `() {
// STUBBING
// EXECUTION
viewModel.handleDataResponse()
// VERIFICATION
assertEquals(true, viewModel.dataLiveData.value)
assertEquals(true, viewModel.currentDeviceTypeLiveData.value)
}
It gives me this when I run the test
Expected : true
Actual :null
dependencies
testImplementation 'androidx.arch.core:core-testing:2.1.0'
testImplementation "io.mockk:mockk:1.12.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0"
Some tips that helped me:
run your test in runBlockingTest
create variable for live data before sending in assert function
#Test
fun `handleDataResponse - Handle connection success `() {
runBlockingTest{
// STUBBING
// EXECUTION
viewModel.handleDataResponse()
val dataLiveData = viewModel.dataLiveData.value
val currentDeviceTypeLiveData = viewModel.currentDeviceTypeLiveData.value
// VERIFICATION
assertEquals(true, dataLiveData)
assertEquals(true, currentDeviceTypeLiveData)
}
}
Add this in test Class
#get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
Declare
private val testCoroutineDispatcher = TestCoroutineDispatcher()
and Add this in setUp()
Dispatchers.setMain(testCoroutineDispatcher)
Add this in tearDown()
Dispatchers.resetMain()
Add this before your test class declaration
#ExperimentalCoroutinesApi
Related
How to start a fragment with a LiveData observer in the test scope with Robolectric
Fragment
class MyFragment(private val viewModel: MyViewModel) : Fragment() {
...
fun myObserver {
...
// If I remove this observer the test will pass.
viewModel.MyLiveData.observe(viewLifecycleOwner, Observer{
...
}
}
}
My Test uses the RobolectricTestRunner so I can launch the fragment in the test scope.
#RunWith(robolectricTestRunner::class)
class MyFragmentTest {
// Executes tasks in the Architecture Components in the same thread
#get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
#Test
fun testOne() {
val viewModel: MyViewModel = mock(MyViewModel::class.java)
val scenario = launchFragmentInContainer(
factory = MainFragmentFactory(viewModel),
fragmentArgs = null
themeResId = R.style.Theme_MyTheme
)
// Tried implementing shadowOf as the error suggests.
}
}
I get the following error when trying to run the test. I've tried setting Main looper to idle before and after instantiating the FragmentScenario.
java.lang.Exception: Main looper has queued unexecuted runnables. This might be the cause of the test failure. You might need a shadowOf(getMainLooper()).idle() call.
I've tried the following
implementing a shadow class for the Main Looper. Annotating the class with Looper mode.
#RunWith(RobolectricTestRunner::class)
#LooperMode(LooperMode.Mode.PAUSED)
class MyFragmentTest {
Adding scenario states
scenario.moveToState(Lifecycle.State.CREATED)
scenario.moveToState(Lifecycle.State.RESUMED)
My Test dependencies.
// Test
testImplementation 'androidx.arch.core:core-testing:2.1.0'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3'
testImplementation "androidx.test.ext:junit-ktx:1.1.2"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.3"
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0'
testImplementation 'junit:junit:4.13.2'
testImplementation 'androidx.test.espresso:espresso-core:3.3.0'
testImplementation "org.robolectric:robolectric:4.5.1"
testImplementation "org.mockito:mockito-android:2.28.2"
// Testing Fragments
debugImplementation "androidx.fragment:fragment-testing:1.3.2"
Links I've used to find a solution'
Testing LiveData Transformations?
https://jeroenmols.com/blog/2019/01/17/livedatajunit5/
I took a look into your repository on github here. Here's what I've found.
Problem 1
Your first problem is that you mock out a ViewModel. So, when you simulate onResume for your Fragment it invokes:
fun liveDataObserver() {
viewModel.scoreLiveData.observe(viewLifecycleOwner, {
//
} )
}
Since viewModel is mocked, scoreLiveData is null and you get an NPE.
To fix this, you also mock out scoreLiveData method so that it returns some acceptable result:
...
val liveData = MutableLiveData<Int>().apply { value = 3 }
val viewModel = mock(MyViewModel::class.java)
doReturn(liveData).`when`(viewModel).scoreLiveData
...
This will fix your testOne completely, but not yet testTwo.
Problem 2
It's related only to your testTwo method. The problem is that you're calling liveDataObserver() in your also block, and that is invoked before your Fragment's viewLifecycleOwner has been set in onCreateView:
...
scenario = launchFragmentInContainer {
MyFragment(viewModel).also {
it.liveDataObserver()
}
}
...
I'm not sure what exactly you're trying to test here, but if you want to verify that you can start observing after Fragment's View has been created, you could do something as following:
...
// make sure your Fragment is started
scenario = launchFragmentInContainer (
factory = MainFragmentFactory(viewModel),
initialState = Lifecycle.State.STARTED
)
// call liveDataObserver on it
scenario.withFragment {
this.liveDataObserver()
}
Full Code
#RunWith(RobolectricTestRunner::class)
class MyFragmentTest {
private lateinit var scenario: FragmentScenario<MyFragment>
#Test
fun testOne() = runBlockingTest {
val liveData = MutableLiveData<Int>().apply { value = 1 }
val viewModel = mock(MyViewModel::class.java)
doReturn(liveData).`when`(viewModel).scoreLiveData
scenario = launchFragmentInContainer(
factory = MainFragmentFactory(viewModel),
fragmentArgs = null,
themeResId = R.style.Theme_TDDScoreKeeper,
initialState = Lifecycle.State.STARTED
)
scenario.moveToState(Lifecycle.State.RESUMED)
scenario.recreate() // Simulates if the phone ran low on resources and the app had to be recreated.
}
#Test
fun testTwo() {
val liveData = MutableLiveData<Int>().apply { value = 1 }
val viewModel = mock(MyViewModel::class.java)
doReturn(liveData).`when`(viewModel).scoreLiveData
scenario = launchFragmentInContainer(
factory = MainFragmentFactory(viewModel),
initialState = Lifecycle.State.STARTED
)
scenario.withFragment {
this.liveDataObserver()
}
}
}
I'm trying to test the following LocalDataSource function, NameLocalData.methodThatFreezes function, but it freezes. How can I solve this? Or How can I test it in another way?
Class to be tested
class NameLocalData(private val roomDatabase: RoomDatabase) : NameLocalDataSource {
override suspend fun methodThatFreezes(someParameter: Something): Something {
roomDatabase.withTransaction {
try {
// calling room DAO methods here
} catch(e: SQLiteConstraintException) {
// ...
}
return something
}
}
}
Test class
#MediumTest
#RunWith(AndroidJUnit4::class)
class NameLocalDataTest {
private lateinit var nameLocalData: NameLocalData
// creates a Room database in memory
#get:Rule
var roomDatabaseRule = RoomDatabaseRule()
#get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
#Before
fun setup() = runBlockingTest {
initializesSomeData()
nameLocalData = NameLocalData(roomDatabaseRule.db)
}
#Test
fun methodThatFreezes() = runBlockingTest {
nameLocalData.methodThatFreezes // test freezes
}
// ... others NameLocalDataTest tests where those functions been tested does not use
// roomDatabase.withTransaction { }
}
Gradle's files configuration
espresso_version = '3.2.0'
kotlin_coroutines_version = '1.3.3'
room_version = '2.2.5'
test_arch_core_testing = '2.1.0'
test_ext_junit_version = '1.1.1'
test_roboletric = '4.3.1'
test_runner_version = '1.2.0'
androidTestImplementation "androidx.arch.core:core-testing:$test_arch_core_testing"
androidTestImplementation "androidx.test.espresso:espresso-core:$espresso_version"
androidTestImplementation "androidx.test.ext:junit:$test_ext_junit_version"
androidTestImplementation "androidx.test:rules:$test_runner_version"
androidTestImplementation "androidx.test:runner:$test_runner_version"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"
Last time I wrote a test for Room database I just simply use runBlock and it worked for me...
Could you take a look into this sample and check if it works for you as well?
Edit:
Ops! I missed this part... I tried this (in the same sample):
I defined a dummy function in my DAO using #Transaction
#Transaction
suspend fun quickInsert(book: Book) {
save(book)
delete(book)
}
I think this is the key of the problem. Add setTransactionExecutor to your Database instantiation.
appDatabase = Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getInstrumentation().context,
AppDatabase::class.java
).setTransactionExecutor(Executors.newSingleThreadExecutor())
.build()
Finally, the test worked using runBlocking
#Test
fun dummyTest() = runBlocking {
val dao = appDatabase.bookDao();
val id = dummyBook.id
dao.quickInsert(dummyBook)
val book = dao.bookById(id).first()
assertNull(book)
}
See this question.
I had tried many things to make this work, used runBlockingTest, used TestCoroutineScope, tried runBlocking, used allowMainThreadQueries, setTransactionExecutor, and setQueryExecutor on my in memory database.
But nothing worked until I found this comment thread in the Threading models in Coroutines and Android SQLite API article in the Android Developers Medium blog, other people mentioned running into this. Author Daniel Santiago said:
I’m not sure what Robolectric might be doing under the hood that could cause withTransaction to never return.
We usually don’t have Robolectric tests but we have plenty of Android Test examples if you want to try that route: https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/room/integration-tests/kotlintestapp/src/androidTest/java/androidx/room/integration/kotlintestapp/test/SuspendingQueryTest.kt
I was able to fix my test by changing it from a Robolectric test to an AndroidTest and by using runBlocking
This is an example from the google source:
#Before
#Throws(Exception::class)
fun setUp() {
database = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
TestDatabase::class.java
)
.build()
booksDao = database.booksDao()
}
#Test
fun runSuspendingTransaction() {
runBlocking {
database.withTransaction {
booksDao.insertPublisherSuspend(
TestUtil.PUBLISHER.publisherId,
TestUtil.PUBLISHER.name
)
booksDao.insertBookSuspend(TestUtil.BOOK_1.copy(salesCnt = 0))
booksDao.insertBookSuspend(TestUtil.BOOK_2)
booksDao.deleteUnsoldBooks()
}
assertThat(booksDao.getBooksSuspend())
.isEqualTo(listOf(TestUtil.BOOK_2))
}
}
Please find below a function using a coroutine to replace callback :
override suspend fun signUp(authentication: Authentication): AuthenticationError {
return suspendCancellableCoroutine {
auth.createUserWithEmailAndPassword(authentication.email, authentication.password)
.addOnCompleteListener(activityLifeCycleService.getActivity()) { task ->
if (task.isSuccessful) {
it.resume(AuthenticationError.SignUpSuccess)
} else {
Log.w(this.javaClass.name, "createUserWithEmail:failure", task.exception)
it.resume(AuthenticationError.SignUpFail)
}
}
}
}
Now I would like to unit testing this function. I am using Mockk :
#Test
fun `signup() must be delegated to createUserWithEmailAndPassword()`() = runBlockingTest {
val listener = slot<OnCompleteListener<AuthResult>>()
val authentication = mockk<Authentication> {
every { email } returns "email"
every { password } returns "pswd"
}
val task = mockk<Task<AuthResult>> {
every { isSuccessful } returns true
}
every { auth.createUserWithEmailAndPassword("email", "pswd") } returns
mockk {
every { addOnCompleteListener(activity, capture(listener)) } returns mockk()
}
service.signUp(authentication)
listener.captured.onComplete(task)
}
Unfortunately this test failed due to the following exception : java.lang.IllegalStateException: This job has not completed yet
I tried to replace runBlockingTest with runBlocking but the test seems to wait in an infinite loop.
Can someone help me with this UT please?
Thanks in advance
As can be seen in this post:
This exception usually means that some coroutines from your tests were scheduled outside the test scope (more specifically the test dispatcher).
Instead of performing this:
private val networkContext: CoroutineContext = TestCoroutineDispatcher()
private val sut = Foo(
networkContext,
someInteractor
)
fun `some test`() = runBlockingTest() {
// given
...
// when
sut.foo()
// then
...
}
Create a test scope passing test dispatcher:
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
private val networkContext: CoroutineContext = testDispatcher
private val sut = Foo(
networkContext,
someInteractor
)
Then in test perform testScope.runBlockingTest
fun `some test`() = testScope.runBlockingTest {
...
}
See also Craig Russell's "Unit Testing Coroutine Suspend Functions using TestCoroutineDispatcher"
In case of Flow testing:
Don't use flow.collect directly inside runBlockingTest. It should be wrapped in launch
Don't forget to cancel TestCoroutineScope in the end of a test. It will stop a Flow collecting.
Example:
class CoroutinesPlayground {
private val job = Job()
private val testDispatcher = StandardTestDispatcher()
private val testScope = TestScope(job + testDispatcher)
#Test
fun `play with coroutines here`() = testScope.runBlockingTest {
val flow = MutableSharedFlow<Int>()
launch {
flow.collect { value ->
println("Value: $value")
}
}
launch {
repeat(10) { value ->
flow.emit(value)
delay(1000)
}
job.cancel()
}
}
}
This is not an official solution, so use it at your own risk.
This is similar to what #azizbekian posted, but instead of calling runBlocking, you call launch.
As this is using TestCoroutineDispatcher, any tasks scheduled to be run without delay are immediately executed. This might not be suitable if you have several tasks running asynchronously.
It might not be suitable for every case but I hope that it helps for simple cases.
You can also follow up on this issue here:
https://github.com/Kotlin/kotlinx.coroutines/issues/1204
If you know how to solve this using the already existing runBlockingTest and runBlocking, please be so kind and share with the community.
class MyTest {
private val dispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(dispatcher)
#Test
fun myTest {
val apiService = mockk<ApiService>()
val repository = MyRepository(apiService)
testScope.launch {
repository.someSuspendedFunction()
}
verify { apiService.expectedFunctionToBeCalled() }
}
}
According to my understanding, this exception occurs when you are using a different dispatcher in your code inside the runBlockingTest { } block with the one that started runBlockingTest { }.
So in order to avoid this, you first have to make sure you inject Dispatchers in your code, instead of hardcoding it throughout your app. If you haven't done it, there's nowhere to begin because you cannot assign a test dispatcher to your test codes.
Then, in your BaseUnitTest, you should have something like this:
#get:Rule
val coroutineRule = CoroutineTestRule()
#ExperimentalCoroutinesApi
class CoroutineTestRule(
val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
) : TestWatcher() {
override fun finished(description: Description?) {
super.finished(description)
Dispatchers.setMain(testDispatcher)
}
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
}
Next step really depends on how you do Depedency Injection. The main point is to make sure your test codes are using coroutineRule.testDispatcher after the injection.
Finally, call runBlockingTest { } from this testDispatcher:
#Test
fun `This should pass`() = coroutineRule.testDispatcher.runBlockingTest {
//Your test code where dispatcher is injected
}
There is an open issue for this problem: https://github.com/Kotlin/kotlinx.coroutines/issues/1204
The solution is to use the CoroutineScope intead of the TestCoroutinScope until the issue is resolved, you can do by replacing
#Test
fun `signup() must be delegated to createUserWithEmailAndPassword()`() =
runBlockingTest {
with
#Test
fun `signup() must be delegated to createUserWithEmailAndPassword()`() =
runBlocking {
None of these answers quite worked for my setup due to frequent changes in the coroutines API.
This specifically works using version 1.6.0 of kotlin-coroutines-test, added as a testImplementation dependency.
#Test
fun `test my function causes flow emission`() = runTest {
// calling this function will result in my flow emitting a value
viewModel.myPublicFunction("1234")
val job = launch {
// Force my flow to update via collect invocation
viewModel.myMemberFlow.collect()
}
// immediately cancel job
job.cancel()
assertEquals("1234", viewModel.myMemberFlow.value)
}
If you have any
Channel
inside the launch, you must call to
Channel.close()
Example code:
val channel = Channel<Success<Any>>()
val flow = channel.consumeAsFlow()
launch {
channel.send(Success(Any()))
channel.close()
}
runBlockingTest deprecated since 1.6.0 and replaced with runTest.
You need to swap arch background executor with one that execute tasks synchronously. eg. For room suspend functions, live data etc.
You need the following dependency for core testing
androidTestImplementation 'androidx.arch.core:core-testing:2.1.0'
Then add the following at the top of test class
#get:Rule
val instantExecutor = InstantTaskExecutorRule()
Explanations
InstantTaskExecutorRule A JUnit Test Rule that swaps the background executor used by the
Architecture Components with a different one which executes each task
synchronously.
You can use this rule for your host side tests that use Architecture
Components
As I mentioned here about fixing runBlockingTest, maybe it could help you too.
Add this dependency if you don't have it
testImplementation "androidx.arch.core:core-testing:$versions.testCoreTesting" (2.1.0)
Then in your test class declare InstantTaskExecutorRule rule:
#get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
Overview
Expected Behavior
Replace mock object initialization using the mockObject function implementation with annotation syntax initialization for JUnit 5 as outlined in the documentation and Medium post by #oleksiyp.
Current Behavior
The test in question is a parameterized test as outlined by #phauer for JUnit 5 which seems to conflict with #ExtendWith(MockKExtension::class). In order to implement tests with LiveData the test must run synchronously in the local unit test using this InstantExecutorExtension designed by #JeroenMols.
Mock object initialization works as expected with the mockObject function, but fails using the annotation #MockK.
Error
Warning message/Build fail:
Repeatable annotations with non-SOURCE retention are not yet supported.
Implementation
mockObject function implementation (Working as expected)
#ExtendWith(InstantExecutorExtension::class)
class NavigateContentTests {
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
#BeforeAll
fun beforeAll() { mockkObject(ContentRepository) }
#AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
#BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
#AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
#ParameterizedTest
#MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { ContentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
ContentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { ContentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
Annotation syntax initialization (Not working due to two extensions #ExtendWith)
#ExtendWith(InstantExecutorExtension::class)
#ExtendWith(MockKExtension::class)
class NavigateContentTests {
// This object should be mocked.
#MockK
lateinit var contentRepository: ContentRepository
private val mainThreadSurrogate = newSingleThreadContext("UI thread")
private val contentViewModel = ContentViewModel()
// This is the stream of tests to run in the Parameterized test below.
private fun NavigateContent() = Stream.of(
NavigateContentTest(
isRealtime = false,
feedType = MAIN,
timeframe = DAY,
mockFeedList = mockDbContentListForDay,
mockContent = mockArticleContent),
...)
#BeforeAll
fun beforeAll() { MockKAnnotations.init(this, relaxUnitFun = true) // turn relaxUnitFun on for }
#AfterAll
fun afterAll() { unmockkAll() // Re-assigns transformation of object to original state prior to mock. }
#BeforeEach
fun beforeEach() { Dispatchers.setMain(mainThreadSurrogate) }
#AfterEach
fun afterEach() {
Dispatchers.resetMain() // Reset main dispatcher to the original Main dispatcher.
mainThreadSurrogate.close()
}
#ParameterizedTest
#MethodSource("NavigateContent")
fun `Navigate Content`(test: NavigateContentTest) = runBlocking {
every { contentRepository.getMainFeedList(test.isRealtime, any()) } returns mockGetMainFeedList(
test.mockFeedList, CONTENT)
every {
contentRepository.queryLabeledContentList(test.feedType)
} returns mockQueryMainContentList(test.mockFeedList)
every { contentRepository.getContent(test.mockContent.id) } returns mockGetContent(test)
// Tests here...
// Verification here...
}
}
Environment
MockK version: 1.9.3
OS: Mac 10.14.6
Kotlin version: 1.3.50
JDK version: 12.0.1
JUnit version: 5.5.1
Type of test: Unit test
This is a bug according to this GitHub issue, as documented by the MockK creator, #oleksiy.
I will update this post once I see the bug is resolved.
The error I have:
The code with the error:
#RunWith(PowerMockRunner::class)
#PrepareForTest(PotatoProvider::class, PotatoConsumer::class)
class WantedButNotInvoked {
#Mock
lateinit var potatoConsumer: PotatoConsumer
#Test
fun potato() {
Observable.just(Potato()).subscribe(potatoConsumer)
verify(potatoConsumer).accept(Potato())
//verify(potatoConsumer).accept(any()) //-> This fails too with the same reason
}
}
data class Potato(val value: Int = 1)
class PotatoConsumer : Consumer<Potato> {
override fun accept(t: Potato?) {
println(t)
}
}
So I making subscribe with this mock(potatoConsumer), and the rxJava have called 'accept', and mockito mark it as interaction, but mockito thinks this interaction is not what I'm expecting, why?
Versions of libraries used her:
mockitoVersion = '2.8.9'
mockitoAndroidVersion = '2.7.22'
powerMockVersion="2.0.2"
kotlinMockito="2.1.0"
rxKotlin = "2.3.0"
rxJavaVersion = "2.2.10"
Kinda workaround
Some fields mocked by powermock, fails on 'verify', but fields mocked with mockito is not;
Mockito can't mock not opened fields, without mock-maker-inline, but mockito conflicts with Powermock mock-maker-inline;
Powermock can delegate calls of mock-maker-inline to other mock-maker-inline(https://github.com/powermock/powermock/wiki/PowerMock-Configuration)
Use Mockito.mock on the failed fields instead of #Mock/Powermock mock injection
Example of the "green" potato test method using PowerMockRunner
#Test
fun potato() {
potatoConsumer = mock() // <-
Observable.just(Potato()).subscribe(potatoConsumer)
verify(potatoConsumer).accept(potato)
}
I am not familiar with PowerMock but I tried this test and it passes:
#Test
fun potato() {
fakePotatoProvider = Mockito.mock(PotatoProvider::class.java)
potatoConsumer = Mockito.mock(PotatoConsumer::class.java)
`when`(fakePotatoProvider.getObservable()).thenReturn(Observable.just(Potato()))
fakePotatoProvider.getObservable().subscribe(potatoConsumer)
verify(potatoConsumer).accept(Potato())
}
Maybe because you aren't passing the same instance of Potato(). Try to refactor your code to this
#Test
fun potato() {
val testPotato = Potato()
`when`(fakePotatoProvider.getObservable()).thenReturn(Observable.just(testPotato))
fakePotatoProvider.getObservable().subscribe(potatoConsumer)
verify(potatoConsumer).accept(testPotato)
}
As I mentioned above, the reason why it might be failing is the constant creation of new instances when passing your Potato object, hance that comparison fails.