Re: [mockito] Problems with programming a mock with when()

4,196 views
Skip to first unread message

Brice Dutheil

unread,
Apr 30, 2013, 6:39:35 AM4/30/13
to moc...@googlegroups.com
Hi Stephan,

Could you provide more code, like the code of 'myMock', the code of the test where you are calling 'bar()' and 'foo()', stacktrace.

It is assured that foo() is called after the mock is programmed by when().

Is it the same for 'bar()' if they are stubbed at all.

Also do you have overloaded foo methods? Maybe one is final?




Cheers,
-- Brice


On Tue, Apr 30, 2013 at 10:39 AM, <s.lu...@gmail.com> wrote:
Hi all,
 
to achieve the mock "myMock" returning an Optional, I was programming it like this:
 
when(myMock.foo(anyList())).thenReturn(Optional.<SomeType> absent());
 
This works but the test sporadically fails with
 
1. a NullPointerException, because the mock returns null instead of absent
2. sometimes with a MockitoException that tells me that I'm trying to stub method bar() for return although it has return type void:

'bar' is a *void method* and it *cannot* be stubbed with a *return value*!
 
The last point is not true, because – as you can see - I'm stubbing foo() and not bar(). 

In about 50% of all runs, the test passes.
 
foo() and bar() are both called from a different thread that is started during setUp. 
It is assured that foo() is called after the mock is programmed by when().
 
NOTE:
In my original code, the methods foo() and bar() have different names with german umlauts.
 
Do you know what my problem could be? Is it with the umlauts?
 
Thanks a lot in advance,
please let me know if you need some further information.
 
Cheers,
 

Stephan

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

s.lu...@gmail.com

unread,
Apr 30, 2013, 7:24:59 AM4/30/13
to moc...@googlegroups.com
Hi Brice,

thank you very much for your immediate reply.

Here's some more code - I hope it's OK for you that it contains the original (and strange :-)) german identifiers:

myMock is a mock of

public interface TürAnzeige {
    void zeigeAn(PersonenDaten daten);

    void zeigeAn(Zutrittsverweigerung verweigerung);

    void zeigeAn(BegehungsAlarm begehung);

    void löscheAnzeige();

    Optional<Arbeitsschein> wähleAus(List<Arbeitsschein> arbeitsscheine);

    boolean öffneTür();

    void türGeschlossen();
}


Please consider wähleAus() as foo() and löscheAnzeige() as bar().

Hence the original when()-call looks like

when(anzeige.wähleAus(anyList())).thenReturn(Optional.<Arbeitsschein> absent());

while anzeige is myMock.


1. NullPointerException

This is sometimes raised for gewählterSchein being null (see red font) because the mock returns null although it shouldn't.

private void doVerarbeiteGoodCase() {
        anzeige.löscheAnzeige();
        ...
        Optional<Arbeitsschein> gewählterSchein = anzeige.wähleAus(arbeitsscheinliste.arbeitsscheine);

        if (!gewählterSchein.isPresent()) {
            ...
        }
        ...
    }


2. MockitoException
The exception that is sometimes raised contains the following message:

org.mockito.exceptions.base.MockitoException:
'löscheAnzeige' is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
    doThrow(exception).when(mock).someVoidMethod();
***
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.
2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.
3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.



As you can see, we neither stub löscheAnzeige()nor do we stub an overloaded method. But - perhaps this is a problem - the interface contains other overloaded methods (zeigeAn()) .

Please keep in mind that 1. + 2. both appear sporadically. 50% of all runs pass the test.

I hope this helps,
thank you so much for your efforts!

Cheers,

Stephan

Brice Dutheil

unread,
Apr 30, 2013, 9:31:59 AM4/30/13
to moc...@googlegroups.com
Oh by the way which version of mockito are you using ?

May I see the code that "entangle" the mock and the thread. Or even better, if you can craft a small JUnit/TestNG test illustrating the issue (you can keep the german identifiers ;)), so I can try it there.

-- Brice




Cheers,

Stephan

s.lu...@gmail.com

unread,
Apr 30, 2013, 10:24:15 AM4/30/13
to moc...@googlegroups.com
Oh sorry, yes, the Mockito version is of interest.

Our test libs are the following:





The code that starts the thread is the following one, called by the setUp-method (@Before):

private void fordereNebenläufigZutrittAn() {
        zutrittsanforderungAbgearbeitet = Executors.newSingleThreadExecutor().submit(
                new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Zutrittsanforderung anforderung = new Zutrittsanforderung();
                            ...
                            station.fordereZutrittAn(anforderung);
                        }
                        catch (RuntimeException erwartet) {
                            ...
                            throw erwartet;
                        }
                    }
                });
    }


Calling station.fordereZutrittAn(anforderung) leads to the call of the above shown method doVerarbeiteGoodCase.

Now how is it assured that
doVerarbeiteGoodCase (which calls the mock anzeige) does not call the mock until it is programmed by when() in the test?

Well,
doVerarbeiteGoodCase reads from a  BlockingQueue while the test writes to the BlockingQueue after when() is called:

@Test
    public void personWähltKeinenArbeitsscheinAus() {
        Arbeitsscheinliste liste = new Arbeitsscheinliste(arbeitsscheine, personenDaten.tagesDosis);

        when(anzeige.wähleAus(anyList())).thenReturn(Optional.<Arbeitsschein> absent());

        //Write to the
BlockingQueue    
...
}

By the way, when I exchanged the Mockito mock by a "handmade" mock (a test implementation of the interface), everything worked fine and stable.

The problem occured for the first time when we added the call
anzeige.löscheAnzeige() to method doVerarbeiteGoodCase(). Remember that
löscheAnzeige is the method which Mockito blames of being mocked although it's void.

I think it's getting quite complicated, so I'll try to reproduce the issue with a smaller sample application with a similar test and post it here....

s.lu...@gmail.com

unread,
Apr 30, 2013, 10:28:07 AM4/30/13
to moc...@googlegroups.com
These are our test libs:

junit-4.11.jar
mockito-core-1.9.5.jar
com.springsource.org.objenesis-1.0.0.jar
fest-assert-1.4.jar
fest-util-1.1.6.jar
xstream-1.3.1.jar
hamcrest-core-1.3.jar

(The screenshot that I inserted into the post before seems to be removed)
Message has been deleted

s.lu...@gmail.com

unread,
Apr 30, 2013, 11:06:48 AM4/30/13
to moc...@googlegroups.com
Fortunately, I was able to reproduce the problem with the MockitoException by very small test. Please execute it a few times until you get the MockitoException:

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;

import org.junit.Before;
import org.junit.Test;

import com.google.common.base.Throwables;
import com.google.common.collect.Queues;

public class ConfuseMockitoTest {
    private final BlockingQueue<String> queue = Queues.newArrayBlockingQueue(5);
    private final SomeAction someAction = mock(SomeAction.class);

    @Before
    public void setUp() {
        Executors.newSingleThreadExecutor().submit(new Runnable() {

            @Override
            public void run() {
                try {
                    someAction.doOtherThings();
                    queue.take();
                }
                catch (InterruptedException e) {
                    Throwables.propagate(e);
                }
            }
        });
    }

    @Test
    public void mockByReturningSomeString_shouldRaiseNoException()
            throws InterruptedException
    {
        when(someAction.getOneThing()).thenReturn("foo");
        queue.put("bar");
    }

    interface SomeAction {
        String getOneThing();

        void doOtherThings();
    }
}

I assume that the exception is caused by the doOtherThings() call on the mock  (red font).
But shouldn't this be allowed?
In this small sample test, the Runnable is the object under test, so it receives the mock and calls it...

I was not able to reproduce the NullPointerException; in real test, this happens when I execute all unit tests and not the single one.

Thanks for your great support,
cheers,

Stephan

Brice Dutheil

unread,
May 6, 2013, 1:54:18 PM5/6/13
to moc...@googlegroups.com
Hi Stephan,

Sorry I completely forgot about you, it was a bit hectic at work.

So well, actually as you are running the mock in thread before stubbing I believe this is the root cause of your problems. Stubbing should be done before any multithreading use.

Here's what could be happening :

The working scenario

JUnit thread                      |  Executor thread
=> setUp(submit the runnable)     |  
=> begin the test method          |
                                  |  => enter the run method
=> call someAction.getOneThing()  |
=> stub the registered call       | 
                                  |  => call someAction.doOtherThings()
...                               |  ...


The failing scenario

JUnit thread                      |  Executor thread
=> setUp(submit the runnable)     |  
=> begin the test method          |
                                  |  => enter the run method
=> call someAction.getOneThing()  |
                                  |  => call someAction.doOtherThings()
=> stub the registered call       | 
...                               |  ...


Now you noticed that the message says that void method cannot be stubbed with a return value, that is because the stubbing syntax uses the last call made to the mock, and because the used stubbing syntax is for value returning methods. 

I'm not sure this behavior of mockito should be changed, to only stub calls made in the same thread, though that would seam reasonable, but I'd like the advice and feedback of the users working with multithreaded code.


I'm not sure what you are trying to achieve in your test, but I would make that any stubbed behavior happens before any other usage of the mock in another thread.

Hope that helps.
-- Brice


--

s.lu...@gmail.com

unread,
May 8, 2013, 4:48:38 AM5/8/13
to moc...@googlegroups.com
Hi Brice,

thanks a lot for your reply.

That's what I assumed, too; Mockito believes that the last called method is the one that is wished to be stubbed. And with multi-threading, this could cause problems.

My problem is, that some tests use the setup which starts the thread in common. And each single test-method has its own stubbing.

Hence it seems to be easier not using Mockito in this case but to mock on my own by creating a test-implementation of the interface.

This works without any errors because the compiler stubs the methods before runtime.

Thanks again for your help,
cheers,

Stephan

Brice Dutheil

unread,
May 10, 2013, 8:48:25 AM5/10/13
to moc...@googlegroups.com
Yay Mockito cannot register a stub on the go, it could be a feature tough.

-- Brice

--
Reply all
Reply to author
Forward
0 new messages