jMock

Bug in Expectations when defining new expectations in the middle of an expectation definition

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Minor Minor
  • Resolution: Fixed
  • Affects Version/s: 2.4.0
  • Fix Version/s: 2.5.0
  • Component/s: JMock 2.x.x Library
  • Labels:
    None
  • Testcase included:
    yes
  • Number of attachments :
    2

Description

We've been playing around with jMock as it seems to be just what we're needing, but we ran across a small issue. I'm uploading an example that will probably explain it best, but I'll attempt to briefly explain it here as well.

Basically, I'm doing the following, where getMockTestParameter(context) itself returns a mocked object.

context.checking(new Expectations()
{
    {
        // The error will occur on the next line.
        one(testObject).testMethod(with(same(getMockTestParameter(context))));
    }
});

However, this throws an unexpected invocation on the line "one(testObject)....", in reference to the mocked parameter (I've uploaded the stack trace).

My initial thought was that mocked objects just couldn't be passed as parameters, which would be a big problem for us, but I kept playing around and found that the following solved the above problem.

// Somehow, storing off the return from getMockTestParameter(context) solves the problem.
final TestParameter testParameter = getMockTestParameter(context);

context.checking(new Expectations()
{
    {
        one(testObject).testMethod(with(same(testParameter)));
    }
});

Apparently, storing off this return value in a local variable solved the problem. While this is workable, it's not very ideal. I'm not quite sure how this has any effect (possibly the fact that it's final??) , but I thought I'd get it out there just in case others run into the same problem and that you were aware of the issue.

Thanks,

Brian

Activity

Hide
Steve Freeman added a comment - - edited

it looks like context might be getting confused by the recursive calls. The class looks more complicated than I think it needs to be. I usually set everything up at the top.

@RunWith(JMock.class)
public class JMockExample {
final Mockery context = new Mockery();
final TestObject testObject = context.mock(TestObject.class);
final TestParameter testParameter = context.mock(TestParameter.class);

and then just use the fields in the test methods.

Show
Steve Freeman added a comment - - edited it looks like context might be getting confused by the recursive calls. The class looks more complicated than I think it needs to be. I usually set everything up at the top. @RunWith(JMock.class) public class JMockExample { final Mockery context = new Mockery(); final TestObject testObject = context.mock(TestObject.class); final TestParameter testParameter = context.mock(TestParameter.class); and then just use the fields in the test methods.
Hide
Brian added a comment -

I agree that in the case of the example I put up, this is ridiculously complex. However, I ran into this issue during a much more complex mocking situation (think corporate enterprise environment ) and I stripped it down to the smallest example that showed the problem. Basically, I need to create mock objects dynamically given particular values, and I have to do this quite a few times, hence the method taking the context. I think you're probably correct about the context getting confused. I suppose I am starting an expectation, then jumping and starting another before it's finished . This probably wasn't a use-case considered, and there's probably a reason. Anyway, like I said, it's easy to work around, and I really just wanted to put it out there for others that may run into the situation.

Brian

Show
Brian added a comment - I agree that in the case of the example I put up, this is ridiculously complex. However, I ran into this issue during a much more complex mocking situation (think corporate enterprise environment ) and I stripped it down to the smallest example that showed the problem. Basically, I need to create mock objects dynamically given particular values, and I have to do this quite a few times, hence the method taking the context. I think you're probably correct about the context getting confused. I suppose I am starting an expectation, then jumping and starting another before it's finished . This probably wasn't a use-case considered, and there's probably a reason. Anyway, like I said, it's easy to work around, and I really just wanted to put it out there for others that may run into the situation. Brian
Hide
Steve Freeman added a comment -

That sounds horrendous and very much not what we're trying to do. I'm not sure we want to consider making it work, although a better warning might help.

Show
Steve Freeman added a comment - That sounds horrendous and very much not what we're trying to do. I'm not sure we want to consider making it work, although a better warning might help.
Hide
Nat Pryce added a comment -

The issue is that your getMockTestParameter method defines expectations. It is called while you are defining the expectations in your test.

So you define expectations in the middle of another expectation, and jMock gets confused.

It's not a use-case we expected, but we'll see what we can do...

(I've edited the summary to reflect what is really going on)

Show
Nat Pryce added a comment - The issue is that your getMockTestParameter method defines expectations. It is called while you are defining the expectations in your test. So you define expectations in the middle of another expectation, and jMock gets confused. It's not a use-case we expected, but we'll see what we can do... (I've edited the summary to reflect what is really going on)
Hide
Nat Pryce added a comment -

Fix committed to SVN

Show
Nat Pryce added a comment - Fix committed to SVN

People

  • Assignee:
    Unassigned
    Reporter:
    Brian
Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: