kaisalmon / mockito

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

Unable to verify spied methods defined in Scala traits #287

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
I realize Mockito is not a Scala lib, but the specs2+Mockito makes a very nice 
combo for testing, so improving this would be very nice :-)

Using 1.8.5/1.9-rc1 I cannot get the following to work:

class MyMockitoTest {
      trait Foo {
         def f1 = "ooh"
      }

      class Bar extends Foo {
        def f2 =  "aah"
      }
      val b = org.mockito.Mockito.spy(new Bar)
      org.mockito.Mockito.verify(b, org.mockito.Mockito.times(0)).f2 
      org.mockito.Mockito.verify(b, org.mockito.Mockito.times(0)).f1 
}

The second call fails with 

java.lang.Exception: 
Missing method call for verify(mock) here:
-> at MyMockitoTest.<init>

Example of correct verification:
    verify(mock).doSomething()

Also, this error might show up because you verify either of: 
final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.

It probably have something to do with the way stackable traits are implemented 
in Scala that confuses the generated wrapper. I've attached the javap output 
from the above classes.

Original issue reported on code.google.com by je...@ingolfs.dk on 2 Nov 2011 at 8:25

Attachments:

GoogleCodeExporter commented 8 years ago

Original comment by brice.du...@gmail.com on 2 Nov 2011 at 8:34

GoogleCodeExporter commented 8 years ago
We're looking for an eager scala dude who wants to take on fixing this :)

Original comment by szcze...@gmail.com on 2 Nov 2011 at 8:47

GoogleCodeExporter commented 8 years ago
I think that this issue should be reproducable with Java only, by using the 
same classes as the one generated by Scala. I'll try to attach an example.

Original comment by etorrebo...@gmail.com on 2 Nov 2011 at 11:08

GoogleCodeExporter commented 8 years ago
Just so that you know I tried to reproduce the same issue, with no success. I 
leave the code here for anyone brave enough to tackle the idea further. This 
code tries to mimick the classes that Scala generates but I was not able to get 
the same weird behavior:

import scala.ScalaObject;

public abstract interface Parent extends ScalaObject {
    public abstract String talk();
}

===============

public abstract class Parent$class {
    public static String talk(Parent $this) {
        return "hello";
    }

    public static void $init$(Parent $this) {
    }
}
====================

import scala.ScalaObject;

public class Child implements Parent, ScalaObject {

   public String talk() {
       return Parent$class.talk(this);
   }
   public String sleep() {
       return "zzzz";
   }
  public Child() {
      Parent$class.$init$(this);
  }
}
====================
import org.junit.Test;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

public class MockitoTest {
    @Test
    public void test() {
        Child child = mock(Child.class);

        verify(child, never()).sleep();
        verify(child, never()).talk();
    }
}

Original comment by etorrebo...@gmail.com on 4 Nov 2011 at 10:53

GoogleCodeExporter commented 8 years ago
I am having this same issue with one difference:

instead of java.lang.Exception I get: 
org.mockito.exceptions.misusing.UnfinishedVerificationException: Missing method 
call for verify(mock)

I don't have a lot to add, but after hours of working on this I can add four 
small pieces of data:

1. It broke when upgrading from Scala 2.8.1 (works fine) to 2.9.1 (breaks with 
no other changes)
2. It works fine if the method is defined in a class (even if declared in a 
trait)
3. After the spied object 'verify' call, it is the _next_ verify call that 
causes the exception
4. Using a debugger, I am able to see a string message inside the 
'verificationMode' that says the method threw a MockitoException and that it 
"cannot evaluate <class name>.toString" (a couple of lines before the 
UnfinishedVerificationException is thrown) 

I would love to help further, but I'm a bit over my head.

Original comment by smeeuw...@gmail.com on 2 Feb 2012 at 2:04

GoogleCodeExporter commented 8 years ago
Wow you've spent a lot of time there, thx :)

Unfortunately, no one in the team actually knows Scala well enough.

The UnfinishedVerificationException  exception you're having makes me think the 
method is final. It might be caused by the compiler. I remember having a 
conversation with someone that told me the compiler has many phases (more than 
20) and apply a lot of transformations on the AST. So maybe at some point the 
compiler adds "final" in the generated bytecode. Or maybe that's something else.

If you know a Scala guru that can help :)

Cheers,
Brice

Original comment by brice.du...@gmail.com on 2 Feb 2012 at 8:23

GoogleCodeExporter commented 8 years ago
Per my #1 above, I  agree it is most likely a Scala code generation "feature" 
that is interacting poorly somehow with Mockito. 

I did dissemble the code, but the verfied methods were not flagged final. For 
now, I've worked around this by changing my trait to an abstract class (not 
possible in all scenarios, but I got lucky), but it would be nice to see this 
get fixed 'some day'. Maybe I should submit to the Scala bug tracker? 

Thanks,
--Scott

Original comment by smeeuw...@gmail.com on 2 Feb 2012 at 2:50

GoogleCodeExporter commented 8 years ago
The problem is that starting with Scala 2.9 the forwarders for trait methods 
which implement the interface of a trait by forwarding to the trait's 
implementation are marked with "ACC_BRIDGE". Mockito seems to miss bridge 
methods when creating a mock.

Original comment by johannes...@googlemail.com on 3 May 2012 at 2:23

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
See issue 340 as well which I created to track the underlying problem.

Original comment by johannes...@googlemail.com on 3 May 2012 at 2:45

GoogleCodeExporter commented 8 years ago

Original comment by brice.du...@gmail.com on 6 Sep 2012 at 3:45