Skip to content
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

Use real objects instead of mocks. #9523

Merged
merged 3 commits into from Sep 7, 2022
Merged

Use real objects instead of mocks. #9523

merged 3 commits into from Sep 7, 2022

Conversation

cpovirk
Copy link
Contributor

@cpovirk cpovirk commented Sep 7, 2022

My motivation for making this change is that ByteBuffer is becoming
sealed

in new versions of Java. This makes it impossible for Mockito's
current default mockmaker to mock it.

That said, Mockito will likely switch its default
mockmaker
to an
alternative that is able to mock sealed classes. However, there are
downside to that, such as slower
performance
,
so it's probably better to leave our options open by avoiding mocking at
all.

And in this case, it's equally easy to use real objects.

As a bonus, I think that real objects makes the code a little easier to
follow: Before, we created mocks that the code under test never
interacted with in any way. (The code just passed them through to a
delegate.) When I first read the tests, I was confused, since I assumed
that the mock we were creating was the same mock that we then passed to
verify at the end of the method. That turned out not to be the case.

Given that, I figured I'd switch not only to a real ByteBuffer but
also to a real OutputStream.

My motivation for making this change is that [`ByteBuffer` is becoming
`sealed`](https://download.java.net/java/early_access/loom/docs/api/java.base/java/nio/ByteBuffer.html)
in new versions of Java. This makes it impossible for Mockito's
_current_ default mockmaker to mock it.

That said, Mockito will likely [switch its default
mockmaker](mockito/mockito#2589) to an
alternative that _is_ able to mock `sealed` classes. However, there are
downside to that, such as [slower
performance](mockito/mockito#2589 (comment)),
so it's probably better to leave our options open by avoiding mocking at
all.

And in this case, it's equally easy to use real objects.

As a bonus, I think that real objects makes the code a little easier to
follow: Before, we created mocks that the code under test never
interacted with in any way. (The code just passed them through to a
delegate.) When I first read the tests, I was confused, since I assumed
that the mock we were creating was the same mock that we then passed to
`verify` at the end of the method. That turned out not to be the case.

Given that, I figured I'd switch not only to a real `ByteBuffer` but
also to a real `OutputStream`.
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Sep 7, 2022

CLA Signed

The committers listed above are authorized under a signed CLA.

@cpovirk
Copy link
Contributor Author

cpovirk commented Sep 7, 2022

The test failure looks unrelated to the change:

io.grpc.okhttp.OkHttpServerTransportTest > maxConnectionIdleTimer_respondWithError FAILED
    org.junit.runners.model.TestTimedOutException: test timed out after 10 seconds
        at java.lang.Object.wait(Native Method)
        at java.io.PipedInputStream.read(PipedInputStream.java:326)
        at java.io.PipedInputStream.read(PipedInputStream.java:377)
        at okio.Okio$2.read(Okio.java:140)
        at okio.RealBufferedSource.request(RealBufferedSource.java:72)
        at okio.RealBufferedSource.require(RealBufferedSource.java:65)
        at io.grpc.okhttp.internal.framed.Http2$Reader.nextFrame(Http2.java:120)
        at io.grpc.okhttp.OkHttpServerTransportTest.verifyGracefulShutdown(OkHttpServerTransportTest.java:1104)
        at io.grpc.okhttp.OkHttpServerTransportTest.maxConnectionIdleTimer_respondWithError(OkHttpServerTransportTest.java:206)

@sanjaypujare
Copy link
Contributor

Should we then replace all occurrences of ByteBuffer mocks with actual instances instead of this one test? Or is this the only one?

Also you are right about the mock not being used in verify (or any other place). So one can very well use (ByteBuffer) null instead of dest without loss of functionality

@cpovirk
Copy link
Contributor Author

cpovirk commented Sep 7, 2022

As far as I know, this is the only mock of ByteBuffer: I found this one by testing in advance of the JDK upgrade inside Google. So, if there were others, I would have expected to see more failures during that testing. (I also don't see any other hits for git grep '[Mm]ock.*ByteBuffer', but there are other ways to create a mock instance besides that.) If we do find others, I agree that it would make sense to change them, too.

@sanjaypujare
Copy link
Contributor

OutputStream is strictly not necessary (other than it being confusing). Do you still want to keep it?

@cpovirk
Copy link
Contributor Author

cpovirk commented Sep 7, 2022

I'm happy either way: Not only is the change not strictly necessary, it also doesn't address all mocking of OutputStream (not to mention InputStream!) in gRPC. Addressing possibly confusion could still be nice, but I'll go whichever way you prefer.

@sanjaypujare
Copy link
Contributor

I'll approve if you remove the OutputStream change. We still need another approver CC @ejona86

@cpovirk
Copy link
Contributor Author

cpovirk commented Sep 7, 2022

Removed, thanks.

@ejona86 ejona86 added the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Sep 7, 2022
@grpc-kokoro grpc-kokoro removed the kokoro:run Add this label to a PR to tell Kokoro the code is safe and tests can be run label Sep 7, 2022
@ejona86
Copy link
Member

ejona86 commented Sep 7, 2022

I'm happy to see a mock die.

@ejona86 ejona86 merged commit 6bafca9 into grpc:master Sep 7, 2022
@cpovirk cpovirk deleted the nomock branch September 8, 2022 14:39
larry-safran pushed a commit to larry-safran/grpc-java that referenced this pull request Oct 6, 2022
My motivation for making this change is that [`ByteBuffer` is becoming
`sealed`](https://download.java.net/java/early_access/loom/docs/api/java.base/java/nio/ByteBuffer.html)
in new versions of Java. This makes it impossible for Mockito's
_current_ default mockmaker to mock it.

That said, Mockito will likely [switch its default
mockmaker](mockito/mockito#2589) to an
alternative that _is_ able to mock `sealed` classes. However, there are
downside to that, such as [slower
performance](mockito/mockito#2589 (comment)),
so it's probably better to leave our options open by avoiding mocking at
all.

And in this case, it's equally easy to use real objects.

As a bonus, I think that real objects makes the code a little easier to
follow: Before, we created mocks that the code under test never
interacted with in any way. (The code just passed them through to a
delegate.) When I first read the tests, I was confused, since I assumed
that the mock we were creating was the same mock that we then passed to
`verify` at the end of the method. That turned out not to be the case.
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants