Skip to content

Caught exception is not the same as the one thrown in .flatMapLatest {} #2910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vkislicins opened this issue Aug 29, 2021 · 1 comment
Closed

Comments

@vkislicins
Copy link

vkislicins commented Aug 29, 2021

I've got a simple Flow:

  fun doThings() {
    getSomeFlow()
      .flatMapLatest { getSomeOtherFlow() }
      .catch { e -> view.showError(e) }
      .launchIn(mainScope)
  }

It's paired with a simple unit test:

  fun doThings_error() {
    val error = IOException("some error")
    coEvery { getSomeOtherFlow() } returns flow { throw error }

    doThings()

    verify { view.showError(error) }
  }

However, the test will fail with:

Verification failed: call 1 of 1: View(#1).showError(eq(java.io.IOException), null())). Only one matching call to View(#1)/showError(Throwable, String) happened, but arguments are not matching:
[0]: argument: java.io.IOException, matcher: eq(java.io.IOException), result: -
[1]: argument: null, matcher: null(), result: +

So to confirm I captured the argument passed into showError

    val slot = slot<IOException>()

    doThings()

    verify { view.showError(capture(slot)) }
    with(slot.captured) {
      assertThat(this).isInstanceOf(error::class.java)
      assertThat(this.message).isEqualTo(error.message)
    }

Which made the test pass. So it seems that the exception object that gets passed to catch {} function is not the same object that gets thrown? I couldn't find this behavior documented anywhere, so I was naturally wondering if this is expected and why. Most likely this is WAD but I'm trying to understand why the object is not the same and come up with the least clunky way of testing this.

Some things I've tried (which didn't make any difference):

  1. Running everything on MainScope to avoid using TestCoroutineScope normally used in my unit tests
  2. Throwing an exception directly instead of mocking.
@qwwdfsad
Copy link
Member

qwwdfsad commented Sep 7, 2021

It seems like you've stepped into stacktrace recovery.

You can disable it via system property, but probably the most efficient solution will be to leverage #2551 when it's there and use it within mock verifiers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants