From: Patrick L. <pli...@ci...> - 2002-12-17 19:07:26
|
I really like the dynamic mock stuff, but it seems there is a pretty major flaw: MockExceptedCalls are mapped using _only_ the methodName. That means I can't expect multiple values for different args on the same method: m.expectAndReturn("findByAndCache", C.args(C.eq(DocumentProblemType.ENTITY_NAME), C.IS_ANYTHING), UtilMisc.toList(dpt1, dpt2)); m.expectAndReturn("findByAndCache", C.args(C.eq(DocumentSubject.ENTITY_NAME), C.IS_ANYTHING), Collections.EMPTY_LIST); m.expectAndReturn("findByAndCache", C.args(C.eq(Publishaction.ENTITY_NAME), C.IS_ANYTHING), Collections.EMPTY_LIST); m.expectAndReturn("findByAndCache", C.args(C.eq(Reviewaction.ENTITY_NAME), C.IS_ANYTHING), Collections.EMPTY_LIST); This code doesn't work becuase the most recent expectation overrides the previous one, and my code ends up failing. Am I using the Mock object incorrectly, or is there a way around this? -Pat |
From: Nat P. <nat...@b1...> - 2002-12-18 02:15:27
|
The way round this problem is to extend the Mock class and implement special behaviour for the methods that you want to be mocked differently -- findByAndCache in your example. If you define findByAndCache in the a class derived from Mock with the same argument types as defined in the mocked interface, the Mock class will call that implementation in preference to its default mock implementation. You can invoke the default implementation by calling the mockCall method if you want to within findByAndCache. E.g. class MockCachedFinder extends Mock { public MockCachedFinder() { super( CachedFinder.class ); } List findByAndCache( String name, ... other args ... ) { ... implement special mock behaviour in here } } In my experience, however, I have often found that having to put logic into a mock object is an indication that there is something wrong with my design. Perhaps you are testing too much in one go, and each interaction should instead be tested in an individual test case. Perhaps your method does too much, and should instead be split into methods with different names that can each be mocked individually. I can't suggest more than that from the little I have seen, but I have often found that following the "Tao of the Mock Object" leads me to cleaner designs. Cheers, Nat. ________________________________ Dr. Nathaniel Pryce B13media Ltd. Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 2EA http://www.b13media.com ----- Original Message ----- From: "Patrick Lightbody" <pli...@ci...> To: <moc...@li...> Sent: Tuesday, December 17, 2002 7:05 PM Subject: [MO-java-dev] Using same method name, different args > I really like the dynamic mock stuff, but it seems there is a pretty major > flaw: MockExceptedCalls are mapped using _only_ the methodName. That means I > can't expect multiple values for different args on the same method: > > m.expectAndReturn("findByAndCache", > C.args(C.eq(DocumentProblemType.ENTITY_NAME), > C.IS_ANYTHING), > UtilMisc.toList(dpt1, dpt2)); > m.expectAndReturn("findByAndCache", > C.args(C.eq(DocumentSubject.ENTITY_NAME), C.IS_ANYTHING), > Collections.EMPTY_LIST); > m.expectAndReturn("findByAndCache", > C.args(C.eq(Publishaction.ENTITY_NAME), C.IS_ANYTHING), > Collections.EMPTY_LIST); > m.expectAndReturn("findByAndCache", > C.args(C.eq(Reviewaction.ENTITY_NAME), C.IS_ANYTHING), > Collections.EMPTY_LIST); > > This code doesn't work becuase the most recent expectation overrides the > previous one, and my code ends up failing. Am I using the Mock object > incorrectly, or is there a way around this? > > -Pat > > > > ------------------------------------------------------- > This sf.net email is sponsored by: > With Great Power, Comes Great Responsibility > Learn to use your power at OSDN's High Performance Computing Channel > http://hpc.devchannel.org/ > _______________________________________________ > Mockobjects-java-dev mailing list > Moc...@li... > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev |
From: Patrick L. <pli...@ci...> - 2002-12-18 02:21:59
|
I resolved this by creating a new MockCall called ArgMockReturnCall: [snip] public Object call(Object[] args) throws Throwable { int argCount = (args == null) ? 0 : args.length; for (Iterator iterator = argMappings.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); Constraint[] constraints = (Constraint[]) entry.getKey(); Object value = entry.getValue(); assertEquals("wrong number of arguments", argCount, constraints.length); if (validArguments(args, constraints)) { return value; } } return defaultValue; } [snip] An example of using it is as follows: // mock finding other GVs ArgMockReturnCall mockCall = new ArgMockReturnCal(Collections.EMPTY_LIST); mockCall.addMapping(C.args(C.eq(DocumentProblemType.ENTITY_NAME), C.IS_ANYTHING), UtilMisc.toList(dpt1, dpt2)); m.setup("findByAndCache", mockCall); So what this does is say: "if findByAndCache is called using the first argument as DocumentProblemType.ENTITY_NAME then return a special List. Otherwise fall back to returning an empty list. I think this MockCall would be very useful to a lot of people. Lots of code people have runs against services (such as Ofbiz) that use the same method name with different args and expect different values returned. -Pat ----- Original Message ----- From: "Nat Pryce" <nat...@b1...> To: "Patrick Lightbody" <pli...@ci...>; <moc...@li...> Sent: Tuesday, December 17, 2002 5:53 PM Subject: Re: [MO-java-dev] Using same method name, different args > The way round this problem is to extend the Mock class and implement special > behaviour for the methods that you want to be mocked differently -- > findByAndCache in your example. If you define findByAndCache in the a class > derived from Mock with the same argument types as defined in the mocked > interface, the Mock class will call that implementation in preference to its > default mock implementation. You can invoke the default implementation by > calling the mockCall method if you want to within findByAndCache. > > E.g. > > class MockCachedFinder extends Mock { > public MockCachedFinder() { > super( CachedFinder.class ); > } > > List findByAndCache( String name, ... other args ... ) { > ... implement special mock behaviour in here > } > } > > > In my experience, however, I have often found that having to put logic into > a mock object is an indication that there is something wrong with my design. > Perhaps you are testing too much in one go, and each interaction should > instead be tested in an individual test case. Perhaps your method does too > much, and should instead be split into methods with different names that can > each be mocked individually. I can't suggest more than that from the little > I have seen, but I have often found that following the "Tao of the Mock > Object" leads me to cleaner designs. > > Cheers, > Nat. > ________________________________ > Dr. Nathaniel Pryce > B13media Ltd. > Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 2EA > http://www.b13media.com > > > ----- Original Message ----- > From: "Patrick Lightbody" <pli...@ci...> > To: <moc...@li...> > Sent: Tuesday, December 17, 2002 7:05 PM > Subject: [MO-java-dev] Using same method name, different args > > > > I really like the dynamic mock stuff, but it seems there is a pretty major > > flaw: MockExceptedCalls are mapped using _only_ the methodName. That means > I > > can't expect multiple values for different args on the same method: > > > > m.expectAndReturn("findByAndCache", > > C.args(C.eq(DocumentProblemType.ENTITY_NAME), > > C.IS_ANYTHING), > > UtilMisc.toList(dpt1, dpt2)); > > m.expectAndReturn("findByAndCache", > > C.args(C.eq(DocumentSubject.ENTITY_NAME), C.IS_ANYTHING), > > Collections.EMPTY_LIST); > > m.expectAndReturn("findByAndCache", > > C.args(C.eq(Publishaction.ENTITY_NAME), C.IS_ANYTHING), > > Collections.EMPTY_LIST); > > m.expectAndReturn("findByAndCache", > > C.args(C.eq(Reviewaction.ENTITY_NAME), C.IS_ANYTHING), > > Collections.EMPTY_LIST); > > > > This code doesn't work becuase the most recent expectation overrides the > > previous one, and my code ends up failing. Am I using the Mock object > > incorrectly, or is there a way around this? > > > > -Pat > > > > > > > > ------------------------------------------------------- > > This sf.net email is sponsored by: > > With Great Power, Comes Great Responsibility > > Learn to use your power at OSDN's High Performance Computing Channel > > http://hpc.devchannel.org/ > > _______________________________________________ > > Mockobjects-java-dev mailing list > > Moc...@li... > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev |
From: Nat P. <nat...@b1...> - 2002-12-18 08:50:38
|
That's a much better solution than mine. I thought of the same thing this morning and was going to post a message suggesting it, but you beat me to it. How could I forget that I originally refactored out the the MockCall interface for this very purpose? Doh! Cheers, Nat. ________________________________ Dr. Nathaniel Pryce B13media Ltd. Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 2EA http://www.b13media.com ----- Original Message ----- From: "Patrick Lightbody" <pli...@ci...> To: "Nat Pryce" <nat...@b1...>; <moc...@li...> Sent: Wednesday, December 18, 2002 2:20 AM Subject: Re: [MO-java-dev] Using same method name, different args > I resolved this by creating a new MockCall called ArgMockReturnCall: > > [snip] > public Object call(Object[] args) throws Throwable { > int argCount = (args == null) ? 0 : args.length; > > for (Iterator iterator = argMappings.entrySet().iterator(); > iterator.hasNext();) { > Map.Entry entry = (Map.Entry) iterator.next(); > Constraint[] constraints = (Constraint[]) entry.getKey(); > Object value = entry.getValue(); > > assertEquals("wrong number of arguments", argCount, > constraints.length); > > if (validArguments(args, constraints)) { > return value; > } > } > > return defaultValue; > } > [snip] > > An example of using it is as follows: > > // mock finding other GVs > ArgMockReturnCall mockCall = new ArgMockReturnCal(Collections.EMPTY_LIST); > mockCall.addMapping(C.args(C.eq(DocumentProblemType.ENTITY_NAME), > C.IS_ANYTHING), UtilMisc.toList(dpt1, dpt2)); > m.setup("findByAndCache", mockCall); > > So what this does is say: "if findByAndCache is called using the first > argument as DocumentProblemType.ENTITY_NAME then return a special List. > Otherwise fall back to returning an empty list. > > I think this MockCall would be very useful to a lot of people. Lots of code > people have runs against services (such as Ofbiz) that use the same method > name with different args and expect different values returned. > > -Pat > > > ----- Original Message ----- > From: "Nat Pryce" <nat...@b1...> > To: "Patrick Lightbody" <pli...@ci...>; > <moc...@li...> > Sent: Tuesday, December 17, 2002 5:53 PM > Subject: Re: [MO-java-dev] Using same method name, different args > > > > The way round this problem is to extend the Mock class and implement > special > > behaviour for the methods that you want to be mocked differently -- > > findByAndCache in your example. If you define findByAndCache in the a > class > > derived from Mock with the same argument types as defined in the mocked > > interface, the Mock class will call that implementation in preference to > its > > default mock implementation. You can invoke the default implementation by > > calling the mockCall method if you want to within findByAndCache. > > > > E.g. > > > > class MockCachedFinder extends Mock { > > public MockCachedFinder() { > > super( CachedFinder.class ); > > } > > > > List findByAndCache( String name, ... other args ... ) { > > ... implement special mock behaviour in here > > } > > } > > > > > > In my experience, however, I have often found that having to put logic > into > > a mock object is an indication that there is something wrong with my > design. > > Perhaps you are testing too much in one go, and each interaction should > > instead be tested in an individual test case. Perhaps your method does > too > > much, and should instead be split into methods with different names that > can > > each be mocked individually. I can't suggest more than that from the > little > > I have seen, but I have often found that following the "Tao of the Mock > > Object" leads me to cleaner designs. > > > > Cheers, > > Nat. > > ________________________________ > > Dr. Nathaniel Pryce > > B13media Ltd. > > Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 2EA > > http://www.b13media.com > > > > > > ----- Original Message ----- > > From: "Patrick Lightbody" <pli...@ci...> > > To: <moc...@li...> > > Sent: Tuesday, December 17, 2002 7:05 PM > > Subject: [MO-java-dev] Using same method name, different args > > > > > > > I really like the dynamic mock stuff, but it seems there is a pretty > major > > > flaw: MockExceptedCalls are mapped using _only_ the methodName. That > means > > I > > > can't expect multiple values for different args on the same method: > > > > > > m.expectAndReturn("findByAndCache", > > > C.args(C.eq(DocumentProblemType.ENTITY_NAME), > > > C.IS_ANYTHING), > > > UtilMisc.toList(dpt1, dpt2)); > > > m.expectAndReturn("findByAndCache", > > > C.args(C.eq(DocumentSubject.ENTITY_NAME), > C.IS_ANYTHING), > > > Collections.EMPTY_LIST); > > > m.expectAndReturn("findByAndCache", > > > C.args(C.eq(Publishaction.ENTITY_NAME), C.IS_ANYTHING), > > > Collections.EMPTY_LIST); > > > m.expectAndReturn("findByAndCache", > > > C.args(C.eq(Reviewaction.ENTITY_NAME), C.IS_ANYTHING), > > > Collections.EMPTY_LIST); > > > > > > This code doesn't work becuase the most recent expectation overrides the > > > previous one, and my code ends up failing. Am I using the Mock object > > > incorrectly, or is there a way around this? > > > > > > -Pat > > > > > > > > > > > > ------------------------------------------------------- > > > This sf.net email is sponsored by: > > > With Great Power, Comes Great Responsibility > > > Learn to use your power at OSDN's High Performance Computing Channel > > > http://hpc.devchannel.org/ > > > _______________________________________________ > > > Mockobjects-java-dev mailing list > > > Moc...@li... > > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev > > > > ------------------------------------------------------- > This sf.net email is sponsored by: > With Great Power, Comes Great Responsibility > Learn to use your power at OSDN's High Performance Computing Channel > http://hpc.devchannel.org/ > _______________________________________________ > Mockobjects-java-dev mailing list > Moc...@li... > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev |
From: Patrick L. <pli...@ci...> - 2002-12-18 09:09:47
|
Could something like this be added as a standard MockCall as well as a method in the Mock object. -Pat ----- Original Message ----- From: "Nat Pryce" <nat...@b1...> To: "Patrick Lightbody" <pli...@ci...>; <moc...@li...> Sent: Wednesday, December 18, 2002 12:29 AM Subject: Re: [MO-java-dev] Using same method name, different args > That's a much better solution than mine. I thought of the same thing this > morning and was going to post a message suggesting it, but you beat me to > it. How could I forget that I originally refactored out the the MockCall > interface for this very purpose? Doh! > > Cheers, > Nat. > > ________________________________ > Dr. Nathaniel Pryce > B13media Ltd. > Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 2EA > http://www.b13media.com > > ----- Original Message ----- > From: "Patrick Lightbody" <pli...@ci...> > To: "Nat Pryce" <nat...@b1...>; > <moc...@li...> > Sent: Wednesday, December 18, 2002 2:20 AM > Subject: Re: [MO-java-dev] Using same method name, different args > > > > I resolved this by creating a new MockCall called ArgMockReturnCall: > > > > [snip] > > public Object call(Object[] args) throws Throwable { > > int argCount = (args == null) ? 0 : args.length; > > > > for (Iterator iterator = argMappings.entrySet().iterator(); > > iterator.hasNext();) { > > Map.Entry entry = (Map.Entry) iterator.next(); > > Constraint[] constraints = (Constraint[]) entry.getKey(); > > Object value = entry.getValue(); > > > > assertEquals("wrong number of arguments", argCount, > > constraints.length); > > > > if (validArguments(args, constraints)) { > > return value; > > } > > } > > > > return defaultValue; > > } > > [snip] > > > > An example of using it is as follows: > > > > // mock finding other GVs > > ArgMockReturnCall mockCall = new ArgMockReturnCal(Collections.EMPTY_LIST); > > mockCall.addMapping(C.args(C.eq(DocumentProblemType.ENTITY_NAME), > > C.IS_ANYTHING), UtilMisc.toList(dpt1, dpt2)); > > m.setup("findByAndCache", mockCall); > > > > So what this does is say: "if findByAndCache is called using the first > > argument as DocumentProblemType.ENTITY_NAME then return a special List. > > Otherwise fall back to returning an empty list. > > > > I think this MockCall would be very useful to a lot of people. Lots of > code > > people have runs against services (such as Ofbiz) that use the same method > > name with different args and expect different values returned. > > > > -Pat > > > > > > ----- Original Message ----- > > From: "Nat Pryce" <nat...@b1...> > > To: "Patrick Lightbody" <pli...@ci...>; > > <moc...@li...> > > Sent: Tuesday, December 17, 2002 5:53 PM > > Subject: Re: [MO-java-dev] Using same method name, different args > > > > > > > The way round this problem is to extend the Mock class and implement > > special > > > behaviour for the methods that you want to be mocked differently -- > > > findByAndCache in your example. If you define findByAndCache in the a > > class > > > derived from Mock with the same argument types as defined in the mocked > > > interface, the Mock class will call that implementation in preference to > > its > > > default mock implementation. You can invoke the default implementation > by > > > calling the mockCall method if you want to within findByAndCache. > > > > > > E.g. > > > > > > class MockCachedFinder extends Mock { > > > public MockCachedFinder() { > > > super( CachedFinder.class ); > > > } > > > > > > List findByAndCache( String name, ... other args ... ) { > > > ... implement special mock behaviour in here > > > } > > > } > > > > > > > > > In my experience, however, I have often found that having to put logic > > into > > > a mock object is an indication that there is something wrong with my > > design. > > > Perhaps you are testing too much in one go, and each interaction should > > > instead be tested in an individual test case. Perhaps your method does > > too > > > much, and should instead be split into methods with different names that > > can > > > each be mocked individually. I can't suggest more than that from the > > little > > > I have seen, but I have often found that following the "Tao of the Mock > > > Object" leads me to cleaner designs. > > > > > > Cheers, > > > Nat. > > > ________________________________ > > > Dr. Nathaniel Pryce > > > B13media Ltd. > > > Studio 3a, Aberdeen Business Centre, 22/24 Highbury Grove, London, N5 > 2EA > > > http://www.b13media.com > > > > > > > > > ----- Original Message ----- > > > From: "Patrick Lightbody" <pli...@ci...> > > > To: <moc...@li...> > > > Sent: Tuesday, December 17, 2002 7:05 PM > > > Subject: [MO-java-dev] Using same method name, different args > > > > > > > > > > I really like the dynamic mock stuff, but it seems there is a pretty > > major > > > > flaw: MockExceptedCalls are mapped using _only_ the methodName. That > > means > > > I > > > > can't expect multiple values for different args on the same method: > > > > > > > > m.expectAndReturn("findByAndCache", > > > > C.args(C.eq(DocumentProblemType.ENTITY_NAME), > > > > C.IS_ANYTHING), > > > > UtilMisc.toList(dpt1, dpt2)); > > > > m.expectAndReturn("findByAndCache", > > > > C.args(C.eq(DocumentSubject.ENTITY_NAME), > > C.IS_ANYTHING), > > > > Collections.EMPTY_LIST); > > > > m.expectAndReturn("findByAndCache", > > > > C.args(C.eq(Publishaction.ENTITY_NAME), > C.IS_ANYTHING), > > > > Collections.EMPTY_LIST); > > > > m.expectAndReturn("findByAndCache", > > > > C.args(C.eq(Reviewaction.ENTITY_NAME), C.IS_ANYTHING), > > > > Collections.EMPTY_LIST); > > > > > > > > This code doesn't work becuase the most recent expectation overrides > the > > > > previous one, and my code ends up failing. Am I using the Mock object > > > > incorrectly, or is there a way around this? > > > > > > > > -Pat > > > > > > > > > > > > > > > > ------------------------------------------------------- > > > > This sf.net email is sponsored by: > > > > With Great Power, Comes Great Responsibility > > > > Learn to use your power at OSDN's High Performance Computing Channel > > > > http://hpc.devchannel.org/ > > > > _______________________________________________ > > > > Mockobjects-java-dev mailing list > > > > Moc...@li... > > > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev > > > > > > > > ------------------------------------------------------- > > This sf.net email is sponsored by: > > With Great Power, Comes Great Responsibility > > Learn to use your power at OSDN's High Performance Computing Channel > > http://hpc.devchannel.org/ > > _______________________________________________ > > Mockobjects-java-dev mailing list > > Moc...@li... > > https://lists.sourceforge.net/lists/listinfo/mockobjects-java-dev |