Mocking a Concrete class with JMock

View: New views
3 Messages — Rating Filter:   Alert me  

Mocking a Concrete class with JMock

by T P D-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



I have class with a forwarding method foo:

void foo( Concrete c, String s ) { c.bar( s ); }

I wish to test that foo in fact forwards. Unfortunately for me, Concrete
is a class in a third-party library, and is a Concrete type, not an
interface. Thus I must use ClassImposterizer in Jmock to mock Concrete,
so in my testcase I do this:

@Test
public final void testFoo() {
    Mockery context = new JUnit4Mockery() {{
       setImposteriser(ClassImposteriser.INSTANCE);
    }};

   final Concrete c = context.mock(Concrete.class);
   final String s = "xxx" ;

   // expectations
   context.checking(new Expectations() {{

      oneOf (c).bar(s); // exception gets thrown from here
   }});


   new ClassUnderTest.foo( c, s );
   context.assertIsSatisfied();

}

Unfortunately, Concrete.bar in turn calls a method that throws. That
method is final, so I can't override it. Further, even if I comment out
the line new ClassUnderTest.foo( c, s );, the exception is thrown when
JMock sets up exceptions, not when foo is called.

So how can I test that method ClassUnderTest.foo does forward to
Concrete.bar?

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Mocking a Concrete class with JMock

by Steve Freeman-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

it's hard to tell without a real example, but would this work better  
as a little integration test? Write a test against the real thing?

S.

On 12 Apr 2009, at 05:38, T P D wrote:

> I have class with a forwarding method foo:
>
> void foo( Concrete c, String s ) { c.bar( s ); }
>
> I wish to test that foo in fact forwards. Unfortunately for me,  
> Concrete is a class in a third-party library, and is a Concrete  
> type, not an interface. Thus I must use ClassImposterizer in Jmock  
> to mock Concrete, so in my testcase I do this:
>
> @Test
> public final void testFoo() {
>   Mockery context = new JUnit4Mockery() {{
>      setImposteriser(ClassImposteriser.INSTANCE);
>   }};
>
>  final Concrete c = context.mock(Concrete.class);
>  final String s = "xxx" ;
>
>  // expectations
>  context.checking(new Expectations() {{
>
>     oneOf (c).bar(s); // exception gets thrown from here
>  }});
>
>
>  new ClassUnderTest.foo( c, s );
>  context.assertIsSatisfied();
>
> }
>
> Unfortunately, Concrete.bar in turn calls a method that throws. That  
> method is final, so I can't override it. Further, even if I comment  
> out the line new ClassUnderTest.foo( c, s );, the exception is  
> thrown when JMock sets up exceptions, not when foo is called.
>
> So how can I test that method ClassUnderTest.foo does forward to  
> Concrete.bar?
>

Steve Freeman
Winner of the Agile Alliance Gordon Pask award 2006

http://www.m3p.co.uk

M3P Limited.
Registered office. 2 Church Street, Burnham, Bucks, SL1 7HZ.
Company registered in England & Wales. Number 03689627



---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



Re: Mocking a Concrete class with JMock

by Nat Pryce :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/12 T P D <lists@...>:
>  // expectations
>  context.checking(new Expectations() {{
>     oneOf (c).bar(s); // exception gets thrown from here
>  }});
...
> Unfortunately, Concrete.bar in turn calls a method that throws. That method
> is final, so I can't override it.

If you've mocked out Concrete.bar, it doesn't matter what the real
implementation calls.  The mock object will not be calling it.

> Further, even if I comment out the line
> new ClassUnderTest.foo( c, s );, the exception is thrown when JMock sets up
> exceptions, not when foo is called.

Is 'bar' final?

> So how can I test that method ClassUnderTest.foo does forward to
> Concrete.bar?

Define an interface between ClassUnderTest and Concrete that describes
the service that ClassUnderTest needs performed for it. You can mock
that interface in the unit test of ClassUnderTest.

Write a thin adapter object that maps the interface onto the Concrete
implementation.  You'll have to test that adapter without mock objects
or just rely on it being so simple that end-to-end test coverage will
give you confidence that it works. Adapters like this often do little
more than forward messages through, translating from the domain of
ClassUnderTest to the domain of Concrete, so the latter is usually
sufficient.

--Nat

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email