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 at 10:59
asked Nov 20 at 10:49
Jonik
51.1k55208315
51.1k55208315
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 usingFunSuitesoshould matchPatterndoesn't seem to be available butcaptor.getValue matchand thencase _ => failseems clean enough.
– Jonik
Nov 20 at 12:28
Why do you keep reverting the answer toanywhich 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? (anyproduces "polymorphic expression cannot be instantiated to expected type";any()works.)
– Jonik
Nov 20 at 12:31
Just mix inMatchersto get thematchPatternto work. As foranywithout 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 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 usingFunSuitesoshould matchPatterndoesn't seem to be available butcaptor.getValue matchand thencase _ => failseems clean enough.
– Jonik
Nov 20 at 12:28
Why do you keep reverting the answer toanywhich 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? (anyproduces "polymorphic expression cannot be instantiated to expected type";any()works.)
– Jonik
Nov 20 at 12:31
Just mix inMatchersto get thematchPatternto work. As foranywithout 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 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 usingFunSuitesoshould matchPatterndoesn't seem to be available butcaptor.getValue matchand thencase _ => failseems clean enough.
– Jonik
Nov 20 at 12:28
Why do you keep reverting the answer toanywhich 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? (anyproduces "polymorphic expression cannot be instantiated to expected type";any()works.)
– Jonik
Nov 20 at 12:31
Just mix inMatchersto get thematchPatternto work. As foranywithout 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 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 at 12:34
answered Nov 20 at 11:50
Dima
24k32234
24k32234
Awesome, thanks! I was usingFunSuitesoshould matchPatterndoesn't seem to be available butcaptor.getValue matchand thencase _ => failseems clean enough.
– Jonik
Nov 20 at 12:28
Why do you keep reverting the answer toanywhich 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? (anyproduces "polymorphic expression cannot be instantiated to expected type";any()works.)
– Jonik
Nov 20 at 12:31
Just mix inMatchersto get thematchPatternto work. As foranywithout 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 at 12:34
add a comment |
Awesome, thanks! I was usingFunSuitesoshould matchPatterndoesn't seem to be available butcaptor.getValue matchand thencase _ => failseems clean enough.
– Jonik
Nov 20 at 12:28
Why do you keep reverting the answer toanywhich 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? (anyproduces "polymorphic expression cannot be instantiated to expected type";any()works.)
– Jonik
Nov 20 at 12:31
Just mix inMatchersto get thematchPatternto work. As foranywithout 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 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 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 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 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 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 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 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 at 8:12
Bruno
27018
27018
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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