添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class ClientRegistrationManager {
    private CrudService crudService;
    private UniqueIdGenerator uniqueIdGenerator;
    @SuppressWarnings("UnusedDeclaration")
    public ClientRegistrationManager() {
    @Inject
    public ClientRegistrationManager(@Nonnull final CrudService crudService, @Nonnull final UniqueIdGenerator uniqueIdGenerator) {
        this.crudService = crudService;
        this.uniqueIdGenerator = uniqueIdGenerator;
    public Member register(@Nonnull final String email, @Nonnull final String userExternalId, @Nonnull final String password) {
        final Member existingMember;
        try {
            existingMember = getMemberQueries().getMemberByEmail(email);
        } catch (final NoResultException e) {
            return createNewMemberAndGetClientDetail(email, userExternalId);
        return existingMember;
    @Nonnull
    protected MemberQueries getMemberQueries() {
        return new MemberQueries(crudService);

I wanted to test it by mocking out any external behavior, so I created getMemberQueries() using Pattern - 1 described in doc

I, then write my test as following

public class ClientRegistrationManagerTest {
    @Mock
    private MemberQueries memberQueries;
    @Mock
    private CrudService crudService;
    @Mock
    private UniqueIdGenerator uniqueIdGenerator;
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
    @Test
    public void testMockedMemberQueries() {
        final ClientRegistrationManager clientRegistrationManager = new ClientRegistrationManager(crudService, uniqueIdGenerator);
        Mockito.when(clientRegistrationManager.getMemberQueries()).thenReturn(memberQueries);
        clientRegistrationManager.getMemberQueries();
        assertTrue(true);

When I run this, I get the error as

org.mockito.exceptions.misusing.MissingMethodInvocationException: 
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

Now what it means I need to mock out the entire ClientRegistrationManager, but that the class I want to test, I can not just mock that entire class.

I am trying to understand my options here, I really do not want to depend on persistence layer, that will be too heavy

Well, you are creating an instance of ClientRegistrationManager yourself - so it is no mock - but then passing it to when. I think, the message is very clear: "when() requires an argument which has to be 'a method call on a mock'". Mocks should only be created for the dependencies of the class under test. – Seelenvirtuose Oct 28, 2014 at 13:26 Yes @Seelenvirtuose, I understand that. I am looking for ideas on how to mock new Object() created inside class under test – daydreamer Oct 28, 2014 at 13:27 I do not want to do that, I want to mock the new Object() creation for the class under test – daydreamer Oct 28, 2014 at 13:30 Hmmm ... I do no understand. Maybe the bigger picture is necessary here. Could you describe more? In fact, it never should be necessary to mock the class under test, and it never should be necessary to setup results on method calls of a mocked instance of the class under test (like you did). – Seelenvirtuose Oct 28, 2014 at 13:32

Seelenvirtuose is correct in the comments: The root problem is that you can only call when on mocks and spies, and that it is typically an anti-pattern to mock the class-under-test.

One technique is to use spy, which lets you intercept and verify calls to a real object ("partial mocking"):

final ClientRegistrationManager clientRegistrationManager =
    Mockito.spy(new ClientRegistrationManager(crudService, uniqueIdGenerator);
// doReturn is important because the call to contains a call to the mock
// before Mockito has intercepted it. In your case, this may just create a useless
// real MemberQueries, but in other cases it can throw an exception.
Mockito.doReturn(memberQueries).when(clientRegistrationManager).getMemberQueries();

As Predrag Magic wrote, another way to do this is to create a factory and replace that during the test. This is especially good if you pass in the factory as an optional constructor argument, because then production systems could create and pass in their own MemberQueryFactory and your class would still work as expected.

public class ClientRegistrationManager {
  static class MemberQueriesFactory {
    MemberQueries getMemberQueries() {
      return ObjectFactory.newMemberQueries(crudService);
  /** Package-private. Visible for unit testing. */
  MemberQueriesFactory memberQueriesFactory = new MembersQueryFactory();
@RunWith(MockitoJUnitRunner.class)
public class ClientRegistrationManagerTest {
  @Mock ClientRegistrationManager.MembersQueryFactory mockMembersQueryFactory;
  private ClientRegistrationManager getManagerForTest() {
    ClientRegistrationManager manager = new ClientRegistrationManager();
    manager.memberQueriesFactory = mockMembersQueryFactory;
    return manager;

My favorite way, though, is to skip Mockito and directly override the class-under-test in the test:

@RunWith(MockitoJUnitRunner.class)
public class ClientRegistrationManagerTest {
  @Mock MemberQueries memberQueries;
  private ClientRegistrationManager getManagerForTest() {
    ClientRegistrationManager manager = new ClientRegistrationManager() {
      @Override void getMemberQueries() {
        return memberQueries;
                I like the idea of spy since they are not too intrusive plus I do not have to write too much code to test
– daydreamer
                Nov 2, 2014 at 23:30

One option is to use some kind of object factory to create new objects in classes under test, and then mock that factory.

protected MemberQueries getMemberQueries() {
    return ObjectFactory.newMemberQueries(crudService);

If, for some reason, you want to mock just selected methods of some object instead of the whole object, you can do that with Mockito. Check out this example.

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.