How to verify a method gets called with an object whose some fields may be anyObject() while others have a...
I'm using Mockito with ScalaTest. Consider this simplified example.
Model case class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
In my test I'm mocking a class called BatchRepository which has a method with this signature:
def create(conn: Connection, batch: Batch): Long
Relevant bit of test code:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
The beef is: I'd like to verify that the code under test calls the mocked repository method with whatever Connection and a Batch instance with whatever id and timestamp, but invoicesReceived
being exactly Some(1)
.
Using Mockito, is this possible at all, and if so, how?
The production code creates a new Batch which sets the timestamp to current moment, so I think it's pretty much impossible to create a real Batch object in the test for the verify()
call with the exact same timestamp. So at least for the timestamp I'd need anyObject()
.
I tried many variations, like wrapping the whole Batch in Matchers.eq()
, but I haven't found anything that works:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
I'd be happy to hear I'm using matchers all wrong if there turns out to be some alternative way to use Mockito to test what I want. 🙂
(I was having hard time writing a good name for this question; please edit or leave a comment if you understand what I'm asking and can express it more succinctly.)
scala unit-testing mockito scalatest hamcrest
add a comment |
I'm using Mockito with ScalaTest. Consider this simplified example.
Model case class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
In my test I'm mocking a class called BatchRepository which has a method with this signature:
def create(conn: Connection, batch: Batch): Long
Relevant bit of test code:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
The beef is: I'd like to verify that the code under test calls the mocked repository method with whatever Connection and a Batch instance with whatever id and timestamp, but invoicesReceived
being exactly Some(1)
.
Using Mockito, is this possible at all, and if so, how?
The production code creates a new Batch which sets the timestamp to current moment, so I think it's pretty much impossible to create a real Batch object in the test for the verify()
call with the exact same timestamp. So at least for the timestamp I'd need anyObject()
.
I tried many variations, like wrapping the whole Batch in Matchers.eq()
, but I haven't found anything that works:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
I'd be happy to hear I'm using matchers all wrong if there turns out to be some alternative way to use Mockito to test what I want. 🙂
(I was having hard time writing a good name for this question; please edit or leave a comment if you understand what I'm asking and can express it more succinctly.)
scala unit-testing mockito scalatest hamcrest
add a comment |
I'm using Mockito with ScalaTest. Consider this simplified example.
Model case class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
In my test I'm mocking a class called BatchRepository which has a method with this signature:
def create(conn: Connection, batch: Batch): Long
Relevant bit of test code:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
The beef is: I'd like to verify that the code under test calls the mocked repository method with whatever Connection and a Batch instance with whatever id and timestamp, but invoicesReceived
being exactly Some(1)
.
Using Mockito, is this possible at all, and if so, how?
The production code creates a new Batch which sets the timestamp to current moment, so I think it's pretty much impossible to create a real Batch object in the test for the verify()
call with the exact same timestamp. So at least for the timestamp I'd need anyObject()
.
I tried many variations, like wrapping the whole Batch in Matchers.eq()
, but I haven't found anything that works:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
I'd be happy to hear I'm using matchers all wrong if there turns out to be some alternative way to use Mockito to test what I want. 🙂
(I was having hard time writing a good name for this question; please edit or leave a comment if you understand what I'm asking and can express it more succinctly.)
scala unit-testing mockito scalatest hamcrest
I'm using Mockito with ScalaTest. Consider this simplified example.
Model case class:
case class Batch(batchId: Long,
timestamp: Option[LocalDateTime] = Some(LocalDateTime.now),
invoicesReceived: Option[Int])
In my test I'm mocking a class called BatchRepository which has a method with this signature:
def create(conn: Connection, batch: Batch): Long
Relevant bit of test code:
verify(batchRepository, times(1)).create(anyObject(),
Batch(anyLong(), anyObject(), Matchers.eq(Some(1))))
)
The beef is: I'd like to verify that the code under test calls the mocked repository method with whatever Connection and a Batch instance with whatever id and timestamp, but invoicesReceived
being exactly Some(1)
.
Using Mockito, is this possible at all, and if so, how?
The production code creates a new Batch which sets the timestamp to current moment, so I think it's pretty much impossible to create a real Batch object in the test for the verify()
call with the exact same timestamp. So at least for the timestamp I'd need anyObject()
.
I tried many variations, like wrapping the whole Batch in Matchers.eq()
, but I haven't found anything that works:
Invalid use of argument matchers! 2 matchers expected, 4 recorded [...]
I'd be happy to hear I'm using matchers all wrong if there turns out to be some alternative way to use Mockito to test what I want. 🙂
(I was having hard time writing a good name for this question; please edit or leave a comment if you understand what I'm asking and can express it more succinctly.)
scala unit-testing mockito scalatest hamcrest
scala unit-testing mockito scalatest hamcrest
edited Nov 20 '18 at 10:59
Jonik
asked Nov 20 '18 at 10:49


JonikJonik
51.5k55209316
51.5k55209316
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
The problem is you are trying to verify
two calls at once - create
and Batch.apply
. Can't do that.
One way to do what you want is ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
Awesome, thanks! I was usingFunSuite
soshould matchPattern
doesn't seem to be available butcaptor.getValue match
and thencase _ => fail
seems clean enough.
– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer toany
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type";any()
works.)
– Jonik
Nov 20 '18 at 12:31
Just mix inMatchers
to get thematchPattern
to work. As forany
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase:def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.
– Dima
Nov 20 '18 at 12:34
add a comment |
Have you tried mockito-scala? it supports partial functions as matchers so you could just write
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
Or even better if you use the idiomatic syntax
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391357%2fhow-to-verify-a-method-gets-called-with-an-object-whose-some-fields-may-be-anyob%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The problem is you are trying to verify
two calls at once - create
and Batch.apply
. Can't do that.
One way to do what you want is ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
Awesome, thanks! I was usingFunSuite
soshould matchPattern
doesn't seem to be available butcaptor.getValue match
and thencase _ => fail
seems clean enough.
– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer toany
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type";any()
works.)
– Jonik
Nov 20 '18 at 12:31
Just mix inMatchers
to get thematchPattern
to work. As forany
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase:def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.
– Dima
Nov 20 '18 at 12:34
add a comment |
The problem is you are trying to verify
two calls at once - create
and Batch.apply
. Can't do that.
One way to do what you want is ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
Awesome, thanks! I was usingFunSuite
soshould matchPattern
doesn't seem to be available butcaptor.getValue match
and thencase _ => fail
seems clean enough.
– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer toany
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type";any()
works.)
– Jonik
Nov 20 '18 at 12:31
Just mix inMatchers
to get thematchPattern
to work. As forany
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase:def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.
– Dima
Nov 20 '18 at 12:34
add a comment |
The problem is you are trying to verify
two calls at once - create
and Batch.apply
. Can't do that.
One way to do what you want is ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
The problem is you are trying to verify
two calls at once - create
and Batch.apply
. Can't do that.
One way to do what you want is ArgumentCaptor
:
val captor = ArgumentCaptor.forClass(classOf[Batch])
verify(batchRepository).create(any(), captor.capture)
captor.getValue should matchPattern {
case Batch(_, _, Some(1)) =>
}
// or just `captor.getValue.infoReceived shouldBe Some(1)`
edited Nov 20 '18 at 12:34
answered Nov 20 '18 at 11:50
DimaDima
24.5k32235
24.5k32235
Awesome, thanks! I was usingFunSuite
soshould matchPattern
doesn't seem to be available butcaptor.getValue match
and thencase _ => fail
seems clean enough.
– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer toany
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type";any()
works.)
– Jonik
Nov 20 '18 at 12:31
Just mix inMatchers
to get thematchPattern
to work. As forany
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase:def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.
– Dima
Nov 20 '18 at 12:34
add a comment |
Awesome, thanks! I was usingFunSuite
soshould matchPattern
doesn't seem to be available butcaptor.getValue match
and thencase _ => fail
seems clean enough.
– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer toany
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type";any()
works.)
– Jonik
Nov 20 '18 at 12:31
Just mix inMatchers
to get thematchPattern
to work. As forany
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase:def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.
– Dima
Nov 20 '18 at 12:34
Awesome, thanks! I was using
FunSuite
so should matchPattern
doesn't seem to be available but captor.getValue match
and then case _ => fail
seems clean enough.– Jonik
Nov 20 '18 at 12:28
Awesome, thanks! I was using
FunSuite
so should matchPattern
doesn't seem to be available but captor.getValue match
and then case _ => fail
seems clean enough.– Jonik
Nov 20 '18 at 12:28
Why do you keep reverting the answer to
any
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type"; any()
works.)– Jonik
Nov 20 '18 at 12:31
Why do you keep reverting the answer to
any
which does not compile in my case? Wouldn't it be more useful to have a version that will actually work as-is for me and future readers? (any
produces "polymorphic expression cannot be instantiated to expected type"; any()
works.)– Jonik
Nov 20 '18 at 12:31
Just mix in
Matchers
to get the matchPattern
to work. As for any
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase: def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.– Dima
Nov 20 '18 at 12:34
Just mix in
Matchers
to get the matchPattern
to work. As for any
without parens, I guess, you are right ... Turns out I just have a workaround in my codebase: def any[T] = Matchers.any()
for so long, that I forgot about it :) I was reverting it because I don't appreciate people editing my stuff without asking first.– Dima
Nov 20 '18 at 12:34
add a comment |
Have you tried mockito-scala? it supports partial functions as matchers so you could just write
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
Or even better if you use the idiomatic syntax
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
add a comment |
Have you tried mockito-scala? it supports partial functions as matchers so you could just write
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
Or even better if you use the idiomatic syntax
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
add a comment |
Have you tried mockito-scala? it supports partial functions as matchers so you could just write
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
Or even better if you use the idiomatic syntax
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
Have you tried mockito-scala? it supports partial functions as matchers so you could just write
verify(batchRepository, times(1)).create(any, argMatching({case Batch(_, _, Some(1)) => }))
Or even better if you use the idiomatic syntax
batchRepository.create(*, argMatching({case Batch(_, _, Some(1)) => })) was called
answered Nov 28 '18 at 8:12


BrunoBruno
35128
35128
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391357%2fhow-to-verify-a-method-gets-called-with-an-object-whose-some-fields-may-be-anyob%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown