|
View:
New views
4 Messages
—
Rating Filter:
Alert me
|
|
|
Expextations return an Object that then mocks a methodI am new to JMock and trying to apply it to some JMS code.
Perhaps I have chosen poor design, but I am having a difficult time getting the expectations to function as I understand they should. In particular, if the method I am testing creates a new object, and then calls a method with the newly created object, how is the situation properly mocked? Here is the code and trace: public final class MDItemPublisher implements MDItemPublisherI{ private final static Logger log = AtsLogMgr .getInstance(MDItemPublisher.class.getPackage().getName()); // JMS iv's private final String topicName; private final TopicSession topicSession; private final TopicPublisher tpub; protected MDItemPublisher(final String topicName, final TopicSession topicSession, final TopicPublisher tpub) { this.topicName = topicName; this.topicSession = topicSession; this.tpub = tpub; } @Override public final void publishMD(final MarketDataQuoteI msg) { try { // get ready to publish final ObjectMessage omsg = topicSession.createObjectMessage(); // set object message to be sent omsg.setObject(msg); // publish the object message tpub.publish(omsg); } catch (JMSException e) { log.warning(e.getMessage()); } } @Override public void destroy() { try { tpub.close(); } catch (JMSException e) { log.warning(e.getMessage()); } } public String toString(){ StringBuffer sb = new StringBuffer(); sb.append("MDItemPublisher:" + topicName); try { sb.append(" delivery mode " + tpub.getDeliveryMode()); sb.append(" priority: " + tpub.getPriority()); sb.append(" ttl: " + tpub.getTimeToLive()); sb.append(" destination: " + tpub.getDestination()); } catch (JMSException e) { log.warning(e.getMessage()); } return sb.toString(); } } public class MDItemPublisherTest { private static Mockery context = new JUnit4Mockery(); @Test public final void testMDItemPublisher() { String topicName = "testTopicName"; TopicSession ts = context.mock(TopicSession.class); TopicPublisher tpub = context.mock(TopicPublisher.class); //execute MDItemPublisher underTest = new MDItemPublisher(topicName, ts, tpub); //verify assertTrue(underTest instanceof MDItemPublisher); context.assertIsSatisfied(); } @Test public final void testPublishMD() throws JMSException { String topicName = "testTopicName"; final TopicSession ts2 = context.mock(TopicSession.class, "ts2"); final TopicPublisher tpub2 = context.mock(TopicPublisher.class, "tpub2"); final ObjectMessage om = context.mock(ObjectMessage.class); MDItemPublisher underTest = new MDItemPublisher(topicName, ts2, tpub2); final MarketDataQuoteI testQuote = context.mock(MarketDataQuoteI.class); context.checking(new Expectations() {{ one(ts2).createObjectMessage(testQuote); will(returnValue(a(ObjectMessage.class))); one (om).setObject(testQuote); one (tpub2).publish((Message) testQuote); }}); //execute underTest.publishMD(testQuote); //verify context.assertIsSatisfied(); } @Test public final void testDestroy() { fail("Not yet implemented"); // TODO } } trace: java.lang.ClassCastException: $Proxy7 at com.ats.bus.md.pub.MDItemPublisherTest$1.<init>(MDItemPublisherTest.java:54) at com.ats.bus.md.pub.MDItemPublisherTest.testPublishMD(MDItemPublisherTest.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42) at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88) at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) |
|
|
Re: Expextations return an Object that then mocks a methodThe problem is here:
one(ts2).createObjectMessage(testQuote); will(returnValue(a(ObjectMessage.class))); the call is returning the class ObjectMessage, it should return an / instance/ of an ObjectMessage. You've already mocked one in the variable 'om'. My reading of the code is the expectations should read: allowing(ts2).createObjectMessage(testQuote); will(returnValue(om)); one(om).setObject(testQuote); one(tpub2).publish(om); there's an interesting point as to whether you should check that the message contents has been set before publishing, but that can wait. Further points: - if you annotate your class with @RunWith(JMock.class); you don't have to explicitly call assertIsSatisfied(); - what is the first test for? It doesn't seem to assert anything more than the type system does. On 16 Aug 2009, at 01:15, quinn wrote: > I am new to JMock and trying to apply it to some JMS code. > [...] 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: Expextations return an Object that then mocks a methodThanks for the quick reply and suggestions.
So my interpretation is that when I call a mock method that creates an object, I should specify the expectation of what will be returned, but also create what is returned if it is used consequently. One question I have is why you would use "allowing" instead of "one". Is it because the code is inside a try clause? Is there a place to find a lot of expectation examples? I seem to be having a problem understanding the semantics. As for the first test, I see your point and will delete it.MarketDataQuoteI.javaMDItemPublisher.javaMDItemPublisherTest.java Unfortunately, your suggestion for the second test does not seem to fix the problem. Here is the trace. java.lang.AssertionError: unexpected invocation: ts2.createObjectMessage() expectations: allowed, never invoked: ts2.createObjectMessage(<marketDataQuoteI>); returns <objectMessage> expected exactly 1 time, never invoked: objectMessage.setObject(<marketDataQuoteI>); returns a default value expected exactly 1 time, never invoked: tpub2.publish(<objectMessage>); returns a default value at org.jmock.internal.InvocationDispatcher.dispatch(InvocationDispatcher.java:56) at org.jmock.Mockery.dispatch(Mockery.java:204) at org.jmock.Mockery.access$000(Mockery.java:37) at org.jmock.Mockery$MockObject.invoke(Mockery.java:246) at org.jmock.internal.InvocationDiverter.invoke(InvocationDiverter.java:27) at org.jmock.internal.ProxiedObjectIdentity.invoke(ProxiedObjectIdentity.java:36) at org.jmock.lib.JavaReflectionImposteriser$1.invoke(JavaReflectionImposteriser.java:33) at $Proxy6.createObjectMessage(Unknown Source) at com.ats.bus.md.pub.MDItemPublisher.publishMD(MDItemPublisher.java:33) at com.ats.bus.md.pub.MDItemPublisherTest.testPublishMD(MDItemPublisherTest.java:53) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) at org.jmock.integration.junit4.JMock$1.invoke(JMock.java:36) at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79) at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87) at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77) at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42) at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88) at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
|
|
|
Re: Expextations return an Object that then mocks a methodWhat that us telling you is that yiur code is calling
"createObjectMessage()" (note: no parameters) but that call is not expected. What you have expected is both createObjectMessage with an object argument *and* setObject on the message that is returned. In JMS you usually do one or the other: create an object message (with no parameter) and then set the message's object, or create an object message for an object in one call. Pick either of those approaches and make your expectations consistent and the test will pass (or at least get a little further). A word of warning, however: JMS is not an API that lends itself to mocking. It's extremely awkward to do simple things in JMS and many if the interfaces are either factories or bags of properties. Setting up the. Expectations is arduous and makes your tests hard to read. Normally that can be taken as feedback about the design: if you change the design to make it easier to write tests you will improve the design and make the software easier to maintain. However, JMS is a standard API so you can't change it in response to that feedback. Therefore I usually use mock objects to drive out the API of an adapter layer between my objects and JMS and write integration tests to test the implementation of that API. I do the same with most third-party libraries. --Nat On Sunday, August 16, 2009, quinn <quinn.tf@...> wrote: > > Thanks for the quick reply and suggestions. > > So my interpretation is that when I call a mock method that creates an > object, I should specify the expectation of what will be returned, but also > create what is returned if it is used consequently. > > One question I have is why you would use "allowing" instead of "one". Is it > because the code is inside a try clause? Is there a place to find a lot of > expectation examples? I seem to be having a problem understanding the > semantics. > > As for the first test, I see your point and will delete it. > http://www.nabble.com/file/p24995890/MarketDataQuoteI.java > MarketDataQuoteI.java > http://www.nabble.com/file/p24995890/MDItemPublisher.java > MDItemPublisher.java > http://www.nabble.com/file/p24995890/MDItemPublisherTest.java > MDItemPublisherTest.java > > Unfortunately, your suggestion for the second test does not seem to fix the > problem. Here is the trace. > > java.lang.AssertionError: unexpected invocation: ts2.createObjectMessage() > expectations: > allowed, never invoked: ts2.createObjectMessage(<marketDataQuoteI>); > returns <objectMessage> > expected exactly 1 time, never invoked: > objectMessage.setObject(<marketDataQuoteI>); returns a default value > expected exactly 1 time, never invoked: tpub2.publish(<objectMessage>); > returns a default value > at > org.jmock.internal.InvocationDispatcher.dispatch(InvocationDispatcher.java:56) > at org.jmock.Mockery.dispatch(Mockery.java:204) > at org.jmock.Mockery.access$000(Mockery.java:37) > at org.jmock.Mockery$MockObject.invoke(Mockery.java:246) > at org.jmock.internal.InvocationDiverter.invoke(InvocationDiverter.java:27) > at > org.jmock.internal.ProxiedObjectIdentity.invoke(ProxiedObjectIdentity.java:36) > at > org.jmock.lib.JavaReflectionImposteriser$1.invoke(JavaReflectionImposteriser.java:33) > at $Proxy6.createObjectMessage(Unknown Source) > at com.ats.bus.md.pub.MDItemPublisher.publishMD(MDItemPublisher.java:33) > at > com.ats.bus.md.pub.MDItemPublisherTest.testPublishMD(MDItemPublisherTest.java:53) > at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) > at > sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) > at > sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) > at java.lang.reflect.Method.invoke(Method.java:597) > at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59) > at org.jmock.integration.junit4.JMock$1.invoke(JMock.java:36) > at > org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98) > at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79) > at > org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87) > at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77) > at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42) > at > org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88) > at > org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51) > at > org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44) > at > org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27) > at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37) > at > org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42) > at > org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38) > at > org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386) > at > org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196) > > > > Steve Freeman-2 wrote: >> >> The problem is here: >> >> one(ts2).createObjectMessage(testQuote); >> will(returnValue(a(ObjectMessage.class))); >> >> the call is returning the class ObjectMessage, it should return an / >> instance/ of an ObjectMessage. You've already mocked >> one in the variable 'om'. My reading of the code is the expectations >> should read: >> >> allowing(ts2).createObjectMessage(testQuote); will(returnValue(om)); >> one(om).setObject(testQuote); >> one(tpub2).publish(om); >> >> there's an interesting point as to whether you should check that the >> message contents has been set before publishing, but that can wait. >> >> Further points: >> - if you annotate your class with @RunWith(JMock.class); you don't >> have to explicitly call assertIsSatisfied(); >> - what is the first test for? It doesn't seem to assert anything more >> than the type system does. >> >> On 16 Aug 2009, at 01:15, quinn wrote: >>> I am new to JMock and trying to apply it to some JMS code. >>> [...] >> >> 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 >> >> >> >> > > -- > View this message in context: http://www.nabble.com/Expextations-return-an-Object-that-then-mocks-a-method-tp24989274p24995890.html > Sent from the jMock - User mailing list archive at Nabble.com. > > > --------------------------------------------------------------------- > To unsubscribe from this list, please visit: > > http://xircles.codehaus.org/manage_email > > > -- http://www.natpryce.com --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email |
| Free embeddable forum powered by Nabble | Forum Help |