XpdWiki
Set your name in
UserPreferences Edit this page Referenced by
JSPWiki v2.0.52
![]() ![]() |
The original version of the paper that documents MockObjects can be found at: http://www.mockobjects.com/endotesting.html MockMaker creates MockObjects from Java Interfaces. MockObjects infrastructure code can be found at http://www.mockobjects.com MockObjects libraries for other languages: MockObjectsPython, MockObjectsRuby For RonJefferies take on MockObjects see: RonJefferiesOnMockObjects For MartinFowler on MockObjects see: http://martinfowler.com/articles/mocksArentStubs.html A thought. Extensive use of MockObjects allows the testing of the system to test PreConditions as well as PostConditions? and Invariants of classes. PreConditions are an area that is not well served by 'standard' Unit Tests. --TomAyerst That sounds weird to me. Surely you test in the presence of PreConditions, rather than actually testing them? That said, MockObjects make them easier to set up and more explicit. --SteveF Hmm, not sure now. In Design ByContract? there are postconditions and invariants (that it is the responsibility of the called class to ensure) and preconditions (that it is the responsibility of the calling class to ensure). The thought was that, without putting precondition assertions in the system code, you can test that a calling object ensures that the called object is in the correct by putting in a mock called object in place with the requiste expectations. Standard tests only check that the tested object performs its part of the contract properly and ends up in a valid state. Are we agreeing or have I missed something? --TomA I've moved a discussion here from Egroups on UnitTestingAroundThirdParties --SteveF There is a new article on EarthWeb? about Cactus discussing (a little) Mock Objects and In-Container testing (http://softwaredev.earthweb.com/java/article/0,,12082_793701,00.html). I'm sorry if everything written is not accurate or not complete but bear in mind that it was written by a journalist ... ! :) (nah, just kidding) --VincentMassol Something I miss in most MockObjects discussions: MockObjects are easy to use if your class only uses objects passed as parameters. But what about objects that are owned/created inside the class under test? Unless the objects are created using some kind of factory method that you can override, it's near impossible to swap in the MockObject. That's the main reason stubs normally are swapped in at compile time. I've found that the best approach is to use factories which you pass in to the object which needs to create other objects. This make it easy to swap in other implementations mock or other wise and it allows you to test that the internal objects are being created. i.e. your passing in the right arguments, creating the right number of objects. I've also found that is can help with memory management e.g. public void createMyObject(...){ try{ new MemoryHungryObject(...); }catch(OutOfMemoryError e){ // Usually it's a really bad idea to catch this // eek. not memory. ask some memory manager object to try // releasing some objects (probably in Hash Maps) cacheManager.release(); new MemoryHungryObject(...); } } The MockObject project is starting to produce factories for standard Java objects like java.io.File so that mock implementations can be used. It doe's mean we have to create proper interfaces for object to though. Hence the creation of alt.java.io.File, alt.java.io.FileImpl? with allow us to use com.mockobjects.io.File woo hoo -- JeffMartin I've used MockObjects a lot in C++ (and like them) and it is tempting to include "test-only" methods in your class that allow you to swap in the MockObject. But that's not a nice solution. Do you encourage a programming style where objects have no members but only use parameters? Looks like a very restrictive version of the DemeterLaw?... Any comments? --ErnestoGuisado Quite often we might add, say, an extra constructor that accepts one of the internal objects. The default constructor will create a real instance. In practice, this doesn't hurt very much and sometimes proves really useful. We also tend to write more factory objects than is common but, again, that often proves useful after the fact. I can imagine this being especially true in C++. We also keep our classes small, so we tend to avoid too many instance variables. --SteveF In some languages, you can pass mock objects as arguments to the constructor that have default values which create the real objects. So the common case initialises the object correctly, but passing in constructor arguments overrides that initialisation and allows mock objects to be used instead. E.g. in Python: class Reactor: def __init__( self, event_queue = System_Event_Queue() ): self.event_queue = event_queue def run( self ): while 1: event = event_queue.wait_for_event() if event.type == EVENT_QUIT: return else: dispatch_event( event ) # Create a reactor that dispatches events from the system event queue reactor = Reactor() # Create a reactor that dispatches mocked events mock_queue = Mock_Event_Queue() reactor = Reactor( mock_queue ) --- Saw a nice article on using mock objects with Aspect-J on IBM developer works (http://www-106.ibm.com/developerworks/library/j-aspectj2/index.html) -- VanEmmenis (28-Aug-02) --- Here's a plug for NMock (http://nmock.truemesh.com/) - a very simple to use dynamic mock object library.³host³³date³February 18, 2003³agent³Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.2.1) Gecko/20021130³MockObjects Refactoring code to accomodate tests has always seemed to me to be somewhat counter intuitive. Whilst I am a believer in design by testing, I would shy away from considering tests as the end goal. Tests should validate the fulfilment of requirements, not define them. When we sat down to write AgileTest ![]()
\ There's an article here ![]() \ (a blatant plug by) Rupert ![]() See also: DynaMock A very neat solution to the problem of using mock objects that are not passed in to the object under test (because they are created/obtained inside the class) is to use a method outlined in this developerworks article http://www-106.ibm.com/developerworks/java/library/j-mocktest.html ![]() For the past few weeks I have been combining the technique of "Extract the creation code into a (protected) factory method, override this factory method in a test subclass (anonymous inner subclass), and then make the overridden method return a mock object instead. Finally, if practical, add a unit test that requires the original object's factory method to return an object of the correct type". At Wordtracker we occasionally use an automated system for overriding the factories which for want of a better name we have called PartialMocks. Sometimes I like to refactor the code a little rather than add the extra logic from optional parameters. -- MarcuS
Inserting Mocks: The Simplest Approach? How about using reflection to slip mocks into place as part of the test setup? For example: import junit.framework.TestCase; import java.lang.reflect.Field; public class AccessControlTest extends TestCase { public void test_renamePerson() throws Exception { Person person = new Person("Miles Daffin"); String newName = "Daffy Duck"; String fieldName = "_name"; Field nameField = person.getClass().getDeclaredField(fieldName); nameField.setAccessible(true); nameField.set(person, newName); assertEquals("value of field " +fieldName, newName, person.getName()); } } class Person { private String _name; public Person(String name) { _name = name; } public String getName() { return _name; } } It is a simple matter to build a test utility class to handle this task, and I think it is better than the AspectJ I think the simple answer to that is "Expectations". I.e the Mock isn't just there for show, you verify it at the endWe originally came up with the name MockObjects but discovered the power is in Expectations. The DynaMock library is IMHO the best implementation of this. (Does the previous comment belong in this section? If so then I don't understand how it relates to my suggestion for inserting mocks. The test case is there to prove that the value of the _name field has been reset, not as a demo of using the approach with a mock... --MilesD) I have used junit-addons PrivateAccessor? utility to do exactly this (http://junit-addons.sourceforge.net/) but in terms of preference it sits behind either refactoring to push in the dependency via a constructor or using an internal factory method (protected) that I override in the test using an anonymous class. --DanPollitt Could you explain your preferences a little? --MilesD However... I feel that there is an assumption around here that MockObjects are a good thing, no question.
Mock based tests can be a real pain to maintain, e.g. during refactoring. The cook makes a fine omlette but employs a Kitchen Porter (KP) and Miles I'm not sure I agree ;-). I think you're reinforcing the need for Mocks. The mock object is telling you that you've modeled the roles and responsibilities incorrectly in the first place. The fridge should not be part of the cooks contract. The mock test being "a pain to maintain" is a CodeSmell? telling you that you need a cook fridge mediator (the KP). This is TestFirstDesign, if the "once and only once fridge access" is important then the mock test embodies that, good start. It was your choice to make the cook part of it. Feel good that you wrote the correct test. What were you really testing?, I don't think it was the cook or the fridge, I think it was the IPreparationStrategy? (of which KitchenPorter? is an implementation). Nobody would have thought of that to start with, but to blame Mock objects for forcing you into further (IMHO valid) decomposition seems unfair. You're story seems to be "maximum order time not exceeded and no 'food leaks'". However there's no talk of proof that you have a maximum, no talk of optimisation or solving that story mathematically. Without an IPreparationStrategy? how can you ever start being extreme (for example) ploting the averages for various implementations of the strategy, or really going for it and training genetic algorithms using your test in some mock kitchen. This is actually what you need to be testing to proove you've delivered that story. Cook and fridge were a bad start, they had so much pressure on them to be something other than a couple of lines of code. Until know I actually imagined they could cook me an omlette. Lobster Quadrille anybody?-- OliBye Excellent Oli! I see I have some thinking to do, not to say learning. Good stuff. "Training genetic algorithms" eh? What does this involve? (Beyond a top hat, large moustache, chair and whip?) --MilesD
|