spat1978 / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

Stubbing methods sometimes fails #474

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Create an Interface EntityManager with method loadEntity(Class,UUID)

2. In the test have

@Before
    public void setup() throws Exception
        entityManager = mock(EntityManager.class);
    }

3. Create the following method
  private void insertEntity(final TestEntity entity) {
        when(entityManager.loadEntity(eq(TestEntity.class), eq(entity.getUuid()))).thenReturn(entity);
        assertNotNull("loadEntity failed (" + (++assertLoadCounter) + ")",                entityManager.loadEntity(TestEntity.class, entity.getUuid()));
    }

4. call the method "insertEntity" repeatedly with the actual test methods 

What is the expected output? What do you see instead?

Expected: No assertion failures.

Seen instead: Spurious assertion failures. Sometimes none, sometimes after 19, 
sometimes after 40 repetitions.

What version of the product are you using? On what operating system?

Linux 64Bit, java version "1.7.0_51, Mockito 1.9.5, hamcrest-core 1.3 with 
maven 3.0.4. 

Original issue reported on code.google.com by lae...@gmail.com on 20 Feb 2014 at 11:29

GoogleCodeExporter commented 8 years ago
Please don't mock an entityManager. And more generally don't mock type you 
don't own :

http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html
http://www.markhneedham.com/blog/2009/12/13/tdd-only-mock-types-you-own
http://blog.8thlight.com/eric-smith/2011/10/27/thats-not-yours.html
http://stackoverflow.com/questions/1906344/should-you-only-mock-types-you-own

Original comment by brice.du...@gmail.com on 18 Mar 2014 at 7:41

GoogleCodeExporter commented 8 years ago
The EntityManager in above example is an own class.
It just happens to be named EntityManager.

Original comment by lae...@gmail.com on 18 Mar 2014 at 7:57

GoogleCodeExporter commented 8 years ago
OK.

But I need more code to reproduce. It may be one of our most dreaded limitation 
with bridge method. Or something else entirely. But we need more code to see 
what's wrong.

When you say insertEntity is called repeatedly, how is it exactly called ? by 
multiple threads ?
If so you cannot do that with mockito, the stubbing phase has to be done in a 
synchronous way, before the mock is called !

Original comment by brice.du...@gmail.com on 18 Mar 2014 at 8:11

GoogleCodeExporter commented 8 years ago
The test in question runs single-threaded.
Sometimes it works 40 times in a row before failing, sometimes it fails much 
faster.
I currently use as workaround .thenAnswer(new Answer() {... }) pattern, 
comparing the input parameters within my answer method. This workaround seems 
to work flawlessly. 
Sadly I can not (as I am on holiday) provide any more details, such as the 
exact source code, right now. To me it seems as if the matchers sometimes fail. 
If need, I can try to produce a dummy test case showing the problem, using some 
other/new classes.

Original comment by lae...@gmail.com on 18 Mar 2014 at 8:26

GoogleCodeExporter commented 8 years ago
OK, thanks :)

This may look like a bug. But I need to see the code or a dummy test showing 
the issue.

Thanks for reporting by the way !

Original comment by brice.du...@gmail.com on 18 Mar 2014 at 8:36

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
Mocked code:

public class PostingGenerator
{
    public Posting createPostingCopy(Posting inputPosting)
    {
        System.out.println("test"); //never printed!
        return null;
    }
}

Tested code:
public class PostingReversalGenerator
{
    private PostingGenerator postingGenerator;

    public PostingReversalGenerator(PostingGenerator postingGeneratorParam)
    {
        this.postingGenerator = postingGeneratorParam;
    }

    public Posting createPostingReversal(Posting originalPosting)
    {
        System.out.println(originalPosting == null); //never null
        Posting postingReversal = postingGenerator.createPostingCopy(originalPosting);

        System.out.println(postingReversal == null); //sometimes true
        System.out.println(postingGenerator.getClass()); //always mock 

        return postingReversal;
    }
}

Test code:
@RunWith(MockitoJUnitRunner.class)
public class PostingReversalGeneratorTest
{
    @Mock
    private PostingGenerator postingGenerator;

    @InjectMocks
    private PostingReversalGenerator postingReversalGenerator;

    @Test
    public void testCreatePostingReversalInPostingWorkspace()
    {
        Posting posting = new PostingImpl();
        when(postingGenerator.createPostingCopy(any(Posting.class))).thenReturn(new PostingImpl());

        assertNotNull(postingReversalGenerator.createPostingReversal(posting));
    }
}

Description:

postingGenerator.createPostingCopy(any(Posting.class)) returns sometimes NULL 
value.

Operating sys. Windows 7 Enterprise SP1
Mockito ver. 1.9

Original comment by mikes...@gmail.com on 3 Jun 2014 at 1:36

GoogleCodeExporter commented 8 years ago
Did you tried with mockito 1.9.5.
Also I cannot reproduce there.

Original comment by brice.du...@gmail.com on 27 Jun 2014 at 3:59