4

(Disclaimer - EasyMock newb)

According to the documentation (and this post), if I wanted to use EasyMock to generate stub objects, I should use EasyMock.createNiceMock(). A "nice mock" is actually a stub - i.e an object that doesn't participate in validation, just returns values.

However, the following snippet fails for me with an IllegalStateException("missing behavior definition for the preceding method"), on the second foo.translate() line.

Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo); // added this line
foo.translate("a", "b");
foo.translate("a", "b"); // only the second calls throws an exception

Can anyone explain this, or rather tell me how to use EasyMock to create stubs with zero verbosity (o(number_of_exercised_mock_methods)).

Edit - I've noticed that I'm getting these errors almost always when a debugger is attached, but never when it isn't attached. Any idea how that may be related?

Community
  • 1
  • 1
ripper234
  • 222,824
  • 274
  • 634
  • 905

3 Answers3

3

Complementing on Jeff's answer.

From EasyMock's method createNiceMock javadoc:

Creates a mock object that implements the given interface, order checking is disabled by default, and the mock object will return 0, null or false for unexpected invocations.

A mock object created by this method don't need any configuration (expected invocations). You just have to create it and "replay it". Example:

ComplicatedObject stub = EasyMock.createNiceMock();
replay(stub);

Any method call is allowed on the created stub (it won't throw an Exception), and they will always return the default value (0, null or false). If you set up an specific invocation expectation, then you'll have to configure it's return value or you'll get an error (that's your case).

If you want to restrict which methods can be executed (making the test fail if an unexpected method is called), them I'm afraid you'll have to create a regular mock, set up every invocation expectation and a return value for each of those.

Andre Rodrigues
  • 2,214
  • 16
  • 14
1

If your translate method returns a value, you need to setup an expectation for it.

expect(foo.translate("a","b")).andStubReturn(retVal);
Jeff Storey
  • 56,312
  • 72
  • 233
  • 406
  • Isn't a Nice Mock supposed to allow me to not set expectations? This means if k methods are exercised, I need to setup k expectations ... and in this case I'm not interested in the expectations at all, I just want to object to work. – ripper234 May 31 '11 at 06:47
  • I believe that only deals with the verifying of the mock and not the setup. Did you try adding a return value and seeing if it works? Also, if you don't care about the expectation and you just need a dummy object, why bother setting up the expectation at all, just create a nice mock and put it in replay mode. – Jeff Storey May 31 '11 at 14:08
  • "adding a return value..." - that would require setting expects for all methods, which I'm trying to avoid. I don't want to set up expectations at all. I believe the above call fails even if I call replay() after the first line (I'll try it out next time I'm at work). – ripper234 Jun 01 '11 at 04:38
  • Oh, I missed something in your code. You didn't actually create a nice mock, you created a standard mock with EasyMock.createMock. Use EasyMock.createNiceMock to create a nice mock. – Jeff Storey Jun 01 '11 at 13:50
  • @Jeff, wait, what? I'll check this and get back to you, I was sure I tried a nice mock. – ripper234 Jun 01 '11 at 15:51
  • Just verified it - the problem persists even with createNiceMock (edited the sample code accordingly) – ripper234 Jun 02 '11 at 07:24
  • 2
    Yes, I have confirmed that you need to add andStubReturn (or andReturn). If you want the method to return default values (i.e. false, 0, etc), just don't set any expectations at all, so something like: Foo foo = createNiceMock(Foo.class); replay(foo); Otherwise, you need to add the return value for methods that return them. – Jeff Storey Jun 02 '11 at 21:37
0

You need to call EasyMock.replay(foo). Before you do that your mock object is in a "record state". From EasyMock documentation:

In the record state (before calling replay), the Mock Object does not behave like a Mock Object, but it records method calls. After calling replay, it behaves like a Mock Object, checking whether the expected method calls are really done.

If you with to create a stub object just call createNiceMock followed by replay:

Foo foo = EasyMock.createNiceMock(Foo.class);
EasyMock.replay(foo);
foo.translate("a", "b");
foo.translate("a", "b");
Volo
  • 28,673
  • 12
  • 97
  • 125