-
Notifications
You must be signed in to change notification settings - Fork 59
Refactor value matchers and postFix dependent syntax #56
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,20 +36,29 @@ The library has independent developers, release cycle and versioning from core m | |
* The usage of `org.mockito.Answer[T]` was removed from the API in favour of [Function Answers](#function-answers) | ||
* If you were using something like `doAnswer(_ => <something>).when ...` to lazily compute a return value when the method is actually called you should now write it like `doAnswer(<something>).when ...`, no need of passing a function as that argument is by-name | ||
* If you have chained return values like `when(myMock.foo) thenReturn "a" thenReturn "b" etc...` the syntax has changed a bit to `when(myMock.foo) thenReturn "a" andThen "b" etc...` | ||
* Idiomatic syntax has some changes to allow support of mixing values and argument matchers [Mix-and-Match](#mix-and-match) | ||
* Idiomatic syntax has some changes to remove postFix operations and also allow support for mixing values and argument matchers [Mix-and-Match](#mix-and-match) | ||
```scala | ||
aMock.bar shouldCallRealMethod => aMock.bar shouldCall realMethod | ||
|
||
aMock wasCalled on bar => aMock.bar was called | ||
aMock wasCalled onlyOn bar => aMock.bar wasCalled onlyHere | ||
aMock was never called on bar => aMock.bar was never called | ||
aMock was never called on bar => aMock.bar wasNever called | ||
aMock wasCalled twiceOn bar => aMock.bar wasCalled twice | ||
aMock wasCalled sixTimesOn bar => aMock.bar wasCalled sixTimes | ||
aMock was never called => aMock.bar wasNever called | ||
aMock was never called again => aMock.bar wasNever calledAgain | ||
|
||
"mocked!" willBe returned by aMock bar => "mocked!" willBe returned by aMock.bar | ||
"mocked!" willBe answered by aMock bar => "mocked!" willBe answered by aMock.bar | ||
((i: Int) => i * 10) willBe answered by aMock bar * => ((i: Int) => i * 10) willBe answered by aMock.bar(*) | ||
theRealMethod willBe called by aMock bar => theRealMethod willBe called by aMock.bar | ||
new IllegalArgumentException willBe thrown by aMock bar => new IllegalArgumentException willBe thrown by aMock.bar | ||
``` | ||
* eqToVal matcher syntax was improved to look more natural [Value Class Matchers](#value-class-matchers) | ||
```scala | ||
verify(myObj).myMethod(eqToVal[MyValueClass](456)) => verify(myObj).myMethod(eqToVal(MyValueClass(456))) | ||
myObj.myMethod(eqToVal[MyValueClass](456)) was called => myObj.myMethod(eqToVal(MyValueClass(456))) was called | ||
``` | ||
|
||
## Getting started | ||
|
||
|
@@ -94,7 +103,7 @@ when(myObj.myMethod(anyVal[MyValueClass]) thenReturn "something" | |
|
||
myObj.myMethod(MyValueClass(456)) shouldBe "something" | ||
|
||
verify(myObj).myMethod(eqToVal[MyValueClass](456)) | ||
verify(myObj).myMethod(eqToVal(MyValueClass(456))) | ||
``` | ||
|
||
## Improved ArgumentCaptor | ||
|
@@ -240,7 +249,7 @@ val aMock = mock[Foo] | |
|
||
when(aMock.bar) thenReturn "mocked!" <=> aMock.bar shouldReturn "mocked!" | ||
when(aMock.bar) thenReturn "mocked!" thenReturn "mocked again!" <=> aMock.bar shouldReturn "mocked!" andThen "mocked again!" | ||
when(aMock.bar) thenCallRealMethod() <=> aMock.bar shouldCallRealMethod | ||
when(aMock.bar) thenCallRealMethod() <=> aMock.bar shouldCall realMethod | ||
when(aMock.bar).thenThrow[IllegalArgumentException] <=> aMock.bar.shouldThrow[IllegalArgumentException] | ||
when(aMock.bar) thenThrow new IllegalArgumentException <=> aMock.bar shouldThrow new IllegalArgumentException | ||
when(aMock.bar) thenAnswer(_ => "mocked!") <=> aMock.bar shouldAnswer "mocked!" | ||
|
@@ -252,14 +261,14 @@ doAnswer(_.getArgument[Int](0) * 10).when(aMock).bar(any) <=> ((i: Int) => | |
doCallRealMethod.when(aMock).bar <=> theRealMethod willBe called by aMock.bar | ||
doThrow(new IllegalArgumentException).when(aMock).bar <=> new IllegalArgumentException willBe thrown by aMock.bar | ||
|
||
verifyZeroInteractions(aMock) <=> aMock was never called | ||
verifyZeroInteractions(aMock) <=> aMock wasNever called | ||
verify(aMock).bar <=> aMock.bar was called | ||
verify(aMock).bar(any) <=> aMock.bar(*) was called | ||
verify(aMock, only).bar <=> aMock.bar wasCalled onlyHere | ||
verify(aMock, never).bar <=> aMock.bar was never called | ||
verify(aMock, never).bar <=> aMock.bar wasNever called | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alternatively it's more consistent with the rest of the api, though I admit There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I'll take a second look There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about also using Not instead of Never seems nicer, the reason I didn't do it before was that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. naming things is hard, and there always will be who thinks it can have a better name, so i suggest juts pick something that compiles in all circumstances and be happy :) i personally think that consistency is more important than following English, easy to remember => quick to use => more productive There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see your point, but one of the main purposes of the DSL is to get rid of awkward reading sentences as well, and the current form is consistent with what it was there before (in both version 1.0.0 and 0.x.x) so I'm gonna keep it like this, history will judge me XD Thanks a lot for your help! |
||
verify(aMock, times(2)).bar <=> aMock.bar wasCalled twice | ||
verify(aMock, times(6)).bar <=> aMock.bar wasCalled sixTimes | ||
verifyNoMoreInteractions(aMock) <=> aMock was never called again | ||
verifyNoMoreInteractions(aMock) <=> aMock wasNever calledAgain | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. alternatively this can be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point |
||
|
||
val order = inOrder(mock1, mock2) <=> InOrder(mock1, mock2) { implicit order => | ||
order.verify(mock2).someMethod() <=> mock2.someMethod() was called | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,17 @@ | ||
package org.mockito.matchers | ||
|
||
import scala.language.experimental.macros | ||
|
||
trait MacroBasedMatchers { | ||
|
||
/** | ||
* Wraps the standard 'ArgumentMatchers.eq()' matcher on the value class provided, this one requires the type to be explicit | ||
*/ | ||
def eqToVal[T](value: Any)(implicit valueClassMatchers: ValueClassMatchers[T]): T = valueClassMatchers.eqToVal(value) | ||
* To be used instead of eqTo when the argument is a value class | ||
*/ | ||
def eqToVal[T](value: T): T = macro ValueClassMatchers.eqToValMatcher[T] | ||
|
||
/** | ||
* Wraps the standard 'any' matcher on the value class provided, this one requires the type to be explicit | ||
* To be used instead of any when the argument is a value class | ||
*/ | ||
def anyVal[T](implicit valueClassMatchers: ValueClassMatchers[T]): T = valueClassMatchers.anyVal | ||
def anyVal[T]: T = macro ValueClassMatchers.anyValMatcher[T] | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are there any other things you can type after
shouldCall
?If not, then I'm not sure it's worth splitting it, just my 2c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was also postfix notation and had a similar compiler error if it had a follow up line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about
shouldReturn whateverRealMethdoReturns
(not really sure what to put as theshouldReturn
parameter, but it would make it more consistent if we can find something that reads nicelyThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think
shouldReturn whateverRealMethdoReturns
looks too long, soshouldCall realMethod
is probably betteranother way looking at it can be
aMock.bar should not be mocked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should not be
would clash with ScalaTest, so it's a no goI wasn't being literal with
whateverRealMethdoReturns
:P just looking for suggestions