How to mock persisting and Entity with Mockito and jUnit
Solution 1
public class AssignIdToArticleAnswer implements Answer<Void> {
private final Long id;
public AssignIdToArticleAnswer(Long id) {
this.id = id;
}
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Article article = (Article) invocation.getArguments()[0];
article.setId(id);
return null;
}
}
And then
doAnswer(new AssignIdToArticleAnswer(1L)).when(em).persist(any(Article.class));
Solution 2
You could use a Mockito Answer
for this.
doAnswer(new Answer<Object>(){
@Override
public Object answer(InvocationOnMock invocation){
Article article = (Article) invocation.getArguments()[0];
article.setId(1L);
return null;
}
}).when(em).persist(any(Article.class));
This tells Mockito that when the persist
method is called, the first argument should have its setId
method invoked.
But if you do this, I don't understand what the purpose of the test would be. You'd really just be testing that the Mockito Answer
mechanism works, not that the code of Article
or of EntityManager
works correctly.
Solution 3
similar answer as above, but with lambdas
doAnswer((InvocationOnMock invocation) -> {
Article article = (Article) invocation.getArguments()[0];
article.setId(1L);
return null;
}).when(em).persist(any(Article.class));
Patrick
Updated on June 09, 2022Comments
-
Patrick over 1 year
I'm trying to find a way to test my entity using Mockito;
This is the simple test method:
@Mock private EntityManager em; @Test public void persistArticleWithValidArticleSetsArticleId() { Article article = new Article(); em.persist(article); assertThat(article.getId(), is(not(0L))); }
How do I best mock the behaviour that the EntityManager changes the Id from 0L to i.e. 1L? Possibly with the least obstructions in readability.
Edit: Some extra information; Outside test-scope the EntityManager is produced by an application-container
-
Dawood ibn Kareem almost 9 yearsMore or less. I was interested to see that you stored the new id in a field of the
Answer
object. I wouldn't have thought of doing that, unless I wanted to reuse theAnswer
in a few places. But why did you delete yours? I think it's different enough from mine that it's worthwhile to have both here. @JBNizet -
JB Nizet almost 9 yearsI deleted it because I was basically the same as yours, but came later. I undeleted it since you think it adds something. In that specific case, storing the id is useless. In fact I borrowed code that I'm actually using where the Answer class is indeed in a top-level class, and can be used for any kind of entity, making it reusable (and reused).
-
Dawood ibn Kareem almost 9 yearsIt's worth noting that with this solution, you can make
AssignIdToArticleAnswer
an inner class of your test class, then use the samedoAnswer
call in several of your test methods. You can even pass in different ids, if it suits you to do so. This makes this solution rather more versatile than my solution, if you're doing anything more than a one-off test. +1. -
Patrick almost 9 yearsThanks for this answer. The reason for this test is more practise-related. I am looking for a way to mock a void-method which runs lines of code when called; For future reference.
-
Dawood ibn Kareem almost 9 years@Patrick - then I recommend you study the Mockito docs that relate to the
Answer
class. This is quite a rich area of the Mockito API, and Mockito has many built-in methods for creatingAnswer
objects for various commonly used operations. -
Patrick almost 9 yearsThe idea is indeed the same but I prefer this method for it's reusability and for better readability in the test-method itself.
-
Brice almost 9 yearsnot a big deal, but for custom answer I would create static factory method that return the answer.
-
Brice almost 9 yearsSame as JB : not a big deal, but for custom answer I would create static factory method that return the answer.
-
Dawood ibn Kareem almost 9 years@Brice Maybe you could post that as an answer, with a code snippet, just for visibility reasons, instead of burying it in the comments under my and JB's answers.
-
Brice almost 9 years;) I know but I'm on a Phone so I keep stuff simple.
-
Villat over 4 yearsShouldn't you use
when(em).persist(isA(Article.class))
instead? -
Dawood ibn Kareem over 4 yearsNot really, it makes absolutely no difference, unless OP is testing a method that persists a whole lot of entities of different classes. If that were the case, he'd have mentioned it in the question. @Villat