Are mocks better than stubs? - unit-testing

A while ago I read the Mocks Aren't Stubs article by Martin Fowler and I must admit I'm a bit scared of external dependencies with regards to added complexity so I would like to ask:
What is the best method to use when unit testing?
Is it better to always use a mock framework to automatically mock the dependencies of the method being tested, or would you prefer to use simpler mechanisms like for instance test stubs?

As the mantra goes 'Go with the simplest thing that can possibly work.'
If fake classes can get the job done, go with them.
If you need an interface with multiple methods to be mocked, go with a mock framework.
Avoid using mocks always because they make tests brittle. Your tests now have intricate knowledge of the methods called by the implementation, if the mocked interface or your implementation changes... your tests break. This is bad coz you'll spend additional time getting your tests to run instead of just getting your SUT to run. Tests should not be inappropriately intimate with the implementation.
So use your best judgment.. I prefer mocks when it'll help save me writing-updating a fake class with n>>3 methods.
Update Epilogue/Deliberation:
(Thanks to Toran Billups for example of a mockist test. See below)
Hi Doug, Well I think we've transcended into another holy war - Classic TDDers vs Mockist TDDers. I think I'm belong to the former.
If I am on test#101 Test_ExportProductList and I find I need to add a new param to IProductService.GetProducts(). I do that get this test green. I use a refactoring tool to update all other references. Now I find all the mockist tests calling this member now blow up. Then I have to go back and update all these tests - a waste of time. Why did ShouldPopulateProductsListOnViewLoadWhenPostBackIsFalse fail? Was it because the code is broken? Rather the tests are broken. I favor the one test failure = 1 place to fix. Mocking freq goes against that. Would stubs be better? If it I had a fake_class.GetProducts().. sure One place to change instead of shotgun surgery over multiple Expect calls. In the end it's a matter of style.. if you had a common utility method MockHelper.SetupExpectForGetProducts() - that'd also suffice.. but you'll see that this is uncommon.
If you place a white strip on the test name, the test is hard to read. Lot of plumbing code for the mock framework hides the actual test being performed.
requires you to learn this particular flavor of a mocking framework

I generally prefer to use mocks because of Expectations. When you call a method on a stub that returns a value, it typically just gives you back a value. But when you call a method on a mock, not only does it return a value, it also enforces the expectation that you set up that the method was even called in the first place. In other words, if you set up an expectation and then don't call that method, an exception gets thrown. When you set an expectation, you are essentially saying "If this method doesn't get called, something went wrong." And the opposite is true, if you call a method on a mock and did not set an expectation, it will throw an exception, essentially saying "Hey, what are you doing calling this method when you didn't expect it."
Sometimes you don't want expectations on every method you're calling, so some mocking frameworks will allow "partial" mocks that are like mock/stub hybrids, in that only the expectations you set are enforced, and every other method call is treated more like a stub in that it just returns a value.
One valid place to use stubs I can think of off the top, though, is when you are introducing testing into legacy code. Sometimes it's just easier to make a stub by subclassing the class you are testing than refactoring everything to make mocking easy or even possible.
And to this...
Avoid using mocks always because they make tests brittle. Your tests now have intricate knowledge of the methods called by the implementation, if the mocked interface changes... your tests break. So use your best judgment..<
...I say if my interface changes, my tests had better break. Because the whole point of unit tests is that they accurately test my code as it exists right now.

It's best to use a combination, and you'll have to use your own judgement. Here's the guidelines I use:
If making a call to external code is part of your code's expected (outward-facing) behavior, this should be tested. Use a mock.
If the call is really an implementation detail which the outside world doesn't care about, prefer stubs. However:
If you're worried that later implementations of the tested code might accidentally go around your stubs, and you want to notice if that happens, use a mock. You're coupling your test to your code, but it's for the sake of noticing that your stub is no longer sufficient and your test needs re-working.
The second kind of mock is a sort of necessary evil. Really what's going on here is that whether you use a stub or a mock, in some cases you have to couple to your code more than you'd like. When that happens, it's better to use a mock than a stub only because you'll know when that coupling breaks and your code is no longer written the way your test thought it would be. It's probably best to leave a comment in your test when you do this so that whoever breaks it knows that their code isn't wrong, the test is.
And again, this is a code smell and a last resort. If you find you need to do this often, try rethinking the way you write your tests.

It just depends on what type of testing you are doing. If you are doing behavior based testing you might want a dynamic mock so you can verify that some interaction with your dependancy occurs. But if you are doing state based testing you might want a stub so you verify values/etc
For example, in the below test you notice that I stub out the view so I can verify a property value is set (state based testing). I then create a dynamic mock of the service class so I can make sure a specific method gets called during the test (interaction / behavior based testing).
<TestMethod()> _
Public Sub Should_Populate_Products_List_OnViewLoad_When_PostBack_Is_False()
mMockery = New MockRepository()
mView = DirectCast(mMockery.Stub(Of IProductView)(), IProductView)
mProductService = DirectCast(mMockery.DynamicMock(Of IProductService)(), IProductService)
mPresenter = New ProductPresenter(mView, mProductService)
Dim ProductList As New List(Of Product)()
ProductList.Add(New Product())
Using mMockery.Record()
SetupResult.For(mView.PageIsPostBack).Return(False)
Expect.Call(mProductService.GetProducts()).Return(ProductList).Repeat.Once()
End Using
Using mMockery.Playback()
mPresenter.OnViewLoad()
End Using
'Verify that we hit the service dependency during the method when postback is false
Assert.AreEqual(1, mView.Products.Count)
mMockery.VerifyAll()
End Sub

Never mind Statist vs. Interaction. Think about the Roles and Relationships. If an object collaborates with a neighbour to get its job done, then that relationship (as expressed in an interface) is a candidate for testing using mocks. If an object is a simple value object with a bit of behaviour, then test it directly. I can't see the point of writing mocks (or even stubs) by hand. That's how we all started and refactored away from that.
For a longer discussion, consider taking a look at http://www.mockobjects.com/book

Read Luke Kanies' discussion of exactly this question in this blog post. He references a post from Jay Fields which even suggests that using [a equivalent to ruby's/mocha's] stub_everything is preferrable to make the tests more robust. To quote Fields' final words: "Mocha makes it as easy to define a mock as it is to define a stub, but that doesn't mean you should always prefer mocks. In fact, I generally prefer stubs and use mocks when necessary."

Related

Don't mock domain objects rule?

The most experienced developer in my current team has set a few hard rules based on best practices we should follow. Among them is "You never ever mock domain object". I asked him why we couldn't but he never had time to give me a proper answer. Now he's away for a week, and I reached a peak distrust to that rule, here's my situation.
My domain object has an Update method with several parameters, one being an interface for a calculator. It then updates a few fields, runs the calculators and assign its results to some other of its fields.
The proper unit test for the Update method itself is reasonably long.
Now I have some piece of code which do a few things then call Update on such a domain object.
I would normally mock the objects, and just check the Update method is being called with the proper arguments. But now, I have to test it's being properly called, by checking its fields and mocking the calculator then same way I did when unit testing the Update method itself. And I would have to do that everywhere the Update methods gets called.
How fun will it be when the Update method change a bit, and every of those tests suddenly break and need refactoring... I feels this rule is just like shooting myself in the foot..
So I need to know, why You never ever mock domain object"?
You never ever mock domain object
This is more of a heuristic than a best practice. And I can imagine that it make sense in some projects.
This heuristic can help to have better tests. Good tests are easy to write, easy to read and they will break as soon as something goes wrong. If you mock your domain model, you will probably also have to mock it's behavior. And if you have some complex behavior in your model, mocking it will be time consuming. The test will also be more fragile (mistakes can happen in predicting the domain model output).
The other alternative is to do sociable unit testing. That means the unit to be tested will not be a single class in isolation but a class and some of its dependencies. In other words, you just use a concrete object of your domain model in the test.
I would normally mock the objects, and just check the Update method is being called with the proper arguments. But now, I have to test it's being properly called, by checking its fields and mocking the calculator then same way I did when unit testing the Update method itself.
Checking that the update method is being called doesn't necessarily mean the success of the test. This is probably not what you want to check to see if your service works correctly. If you pass a concrete class of your model(including the calculators) you won't have to do any useless checks or repeat what has been done in other tests.
One of the differences between this solution and testing classes in isolation is that when there is bug in your domain model, many other tests will fail. But this is totally fine in my opinion since it will have to be fixed anyway.
You never ever mock domain object
There might be different reasons to avoid mocking your domain objects:
Mocking libraries, the same as ORMs, can affect design of your domain objects. They usually require interfaces or virtual methods in C#.
A preference to test against real instances. Very often people use mocking libraries because it is an easy way to create a fake or a stub. Very often you can build an instance of your domain object and use it in your test. Most likely a fact that method Update was called can be easily checked via state change.
I would normally mock the objects, and just check the Update method is being called with the proper arguments. But now, I have to test it's being properly called, by checking its fields and mocking the calculator then same way I did when unit testing the Update method itself.
How fun will it be when the Update method change a bit, and every of those tests suddenly break and need refactoring...
It was already mentioned in the comment that probably Update method has to many responsibilities and that's why is used in lots of use cases.
There are different tastes when it comes to defining a system under test (sut). If you tend to test classes then you often find yourself using mocking libraries. If you tend to test scenarios or behaviors then most likely you will only care about state changes.
You can probably explore a different design for your domain object: Try to split Update method into explicit domain specific methods so each client will trigger a different behavior. Given this approach a "reasonably long" test for the Update method can even become obsolete since it will be tested by other tests.
While Update() is probably not as tailored a method as you would expect from a rich domain model - which may have an impact on test fragility - I agree that you should take "never do X" advice with a grain of salt.
If you understand all the implications and know that the integration test version will be less maintainable, definitely use mocks. You, and not blanket statements or cargo cults, are the ultimate judge to what's better for your system in your context.

Am I doing something fundamentally wrong in my unit tests?

After reading an interesting article about unit testing behavior instead of state, I came to realize that my unit tests often are tightly coupled to my code because I am using mocks.
I cannot image writing unit tests without mocks but the fact is that these mocks are coupling my unit test very much to my code because of the expect andReturn calls.
For example when I create a test that uses a mock, I record all calls to the specific mock and assign return values.
Now when I change the implementation of the actual code for whatever reason, a lot of tests break because that call was not expected by the mock, forcing me to update the unit test also, and effectively forcing me to implement every change twice...
This happens a lot.
Is this issue intrinsic to using mocks, and should I learn to live with it, or am I doing something fundamentally wrong?
Please enlighten me :)
Clear examples coming with the explanation are most welcome of course.
when I create a test that uses a mock,
I record all calls to the specific
mock and assign return values
It sounds like you may be over-specifying expectations.
Try to build as little setup code as possible into your tests: stub (rather than expect) all behavior that doesn't pertain to the current test and only specify return values that are absolutely needed to make your test work.
This answer includes a concise example (as well as an alternative, more detailed explanation).
My experience is to use mocks only at the bounderies of (sub)systems. If I have two classes that are strongly related I do not mock them appart but test them together. An example might be an composite and a visitor. If I test a concrete visitor I do not use a mock for the composite but create real composites. One might argue that this is not a unit test (depends on the definition of what is a unit). But that doesn't matter that much. What I try to achieve is:
Write readable tests (tests without mocks are most of the time more easy to read).
Test only a focused area of code (in the example the concreate visitor and the relevant part of the composite).
Write fast tests (as long as I instantiate only a few classes, in the example the concrete composites, this is not a concern ... watch for transitive creations).
Only if I encounter the boundary of a subsystem I use mocks. Example: I have a composite that can render itself to a renderer I would mock out the renderer if I test the render logic of the composite.
Testing behavior instead of state looks promosing at first but in general I would test state as the resulting tests are easiear to maintain. Mocks are a cannon. Don't crack a nut with a sledgehammer.
If you are fixing the tests because they break, you are not using them as intended.
If the behaviour of a method changes, in test driven development you would first change the test to expect the new behaviour, then implement the new behaviour.
Several good answers here already, but for me a good rule of thumb is to test the requirements of the method, not the implementation. Sometimes that may mean using a mock object because the interaction is the requirement, but you're usually better off testing the return value of the method or the change in state of the object.

What is wrong with Stubs for unit testing?

I just watched this funny YouTube Video about unit testing (it's Hitler with fake subtitles chewing out his team for not doing good unit tests--skip it if you're humor impaired) where stubs get roundly criticized. But I don't understand what wrong with stubs.
I haven't started using a mocking framework and I haven't started feeling the pain from not using one.
Am I in for a world a hurt sometime down the line, having chosen handwritten stubs and fakes instead of mocks (like Rhinomock etc)? (using Fowler's taxonomy)
What are the considerations for picking between a mock and handwritten stub?
There is nothing wrong with stubs, there is room for stubs, mocks... and spies. All are "test doubles", but with different purposes as explained in Mocks and Stubs aren't Spies:
[...] Before moving on, I'd like to
clarify and define some terms in use
here, which I originally discovered in
Gerard Meszaros' xUnit Patterns
book.
A Dummy Object is a placeholder object passed to the system under test
but never used.
A Test Stub provides the system under test with indirect input
A Test Spy provides a way to verify that the system under test performed
the correct indirect output
A Mock Object provides the system under test with both indirect input
and a way to verify indirect output
[...] And you can let this handy chart
guide your decisions:
PS: Mockito - The New Mock Framework on the Block is worth the read too.
I use the following terminology (introduced by Roy Osherove, the author of the Art of Unit-Testing):
A fake is called a stub if you tell it to fake something in case a method is called with such and such parameters. But if you also verify that such call actually took place or took place exactly N times, then such fake is called a mock. In short. a fake is a stub unless you call Verify() on it and then it's a mock.
Obviously, you will need to use stubs in some cases and mocks in others. So, criticizing stubs roundly is probably wrong and using stubs exclusively is probably wrong as well.
If you haven't started using a mocking framework (alternative term: isolation framework), you should keep an eye on them and reevaluate your options frequently. I went from manual mocks to NMock2 to Moq very quickly. Here's an interesting poll of programmers that shows what they use. Manual mocks/stubs are in the minority, but aren't that uncommon.
Mocks are just a lot easier to throw in. They are a real instance of your class, pre-stubbed with the ability to override the action of any method with minimal boilerplate.
There are lots of little considerations such as: If you don't want to deal with any of the methods, you can either have it act as a no-op or fail the test--your choice--but either way virtually no code.
How much boilerplate do you get when you stub out a class? How do you handle it if your class is final? Do you play tricks to get your stub on the classpath first, or do you use different source?
I recommend just starting with the mocks--It's easier all around.
There is nothing wrong with using stubs instead of mocks.
If you want to get technical, mocks are "smart" objects with expectations that can be verified. Stubs are dummy objects that return preset values. See Mocks Aren't Stubs.
But many people (myself included) prefer to do state testing with stubs rather than behavior testing with mocks. You inject a stub into the class under test, you call a method, then you check the state of the class under test. It tends to make for less brittle tests than asserting that the class's internals called method X of a mock object with argument Y.
I don't think you're in for a world of hurt. If you haven't started feeling the pain, you probably don't need an isolation/mocking framework yet. When and if you do, having handwritten stubs/fakes around isn't going to hurt anything.
If you have a lot of interfaces, or if your interfaces have a lot of methods, an isolation/mocking framework can save a lot of time over hand-coding stubs.
I like Moq a lot; I find it easier to use than Rhino Mocks for creating stubs.
Mocks and stubs is used to achieve a real unit test. You just mock all the dependencies, and unit test your class in isolation.
I'm currently using MOQ for mocking and stubbing.

Why is it so bad to mock classes?

I recently discussed with a colleague about mocking. He said that mocking classes is very bad and should not be done, only in few cases.
He says that only interfaces should be mocked, otherwise it's an architecture fault.
I wonder why this statement (I fully trust him) is so correct? I don't know it and would like to be convinced.
Did I miss the point of mocking (yes, I read Martin Fowler's article)
Mocking is used for protocol testing - it tests how you'll use an API, and how you'll react when the API reacts accordingly.
Ideally (in many cases at least), that API should be specified as an interface rather than a class - an interface defines a protocol, a class defines at least part of an implementation.
On a practical note, mocking frameworks tend to have limitations around mocking classes.
In my experience, mocking is somewhat overused - often you're not really interested in the exact interaction, you really want a stub... but mocking framework can be used to create stubs, and you fall into the trap of creating brittle tests by mocking instead of stubbing. It's a hard balance to get right though.
IMHO, what your colleague means is that you should program to an interface, not an implementation. If you find yourself mocking classes too often, it's a sign you broke the previous principle when designing your architecture.
Mocking classes (in contrast to mocking interfaces) is bad because the mock still has a real class in the background, it is inherited from, and it is possible that real implementation is executed during the test.
When you mock (or stub or whatever) an interface, there is no risk of having code executed you actually wanted to mock.
Mocking classes also forces you to make everything, that could possibly be mocked, to be virtual, which is very intrusive and could lead to bad class design.
If you want to decouple classes, they should not know each other, this is the reason why it makes sense to mock (or stub or whatever) one of them. So implementing against interfaces is recommended anyway, but this is mentioned here by others enough.
I would suggest to stay away from mocking frameworks as far as possible. At the same time, I would recommend to use mock/fake objects for testing, as much as possible. The trick here is that you should create built-in fake objects together with real objects. I explain it more in detail in a blog post I wrote about it: http://www.yegor256.com/2014/09/23/built-in-fake-objects.html
Generally you'd want to mock an interface.
While it is possible to mock a regular class, it tends to influence your class design too much for testability. Concerns like accessibility, whether or not a method is virtual, etc. will all be determined by the ability to mock the class, rather than true OO concerns.
There is one faking library called TypeMock Isolator that allows you to get around these limitations (have cake, eat cake) but it's pretty expensive. Better to design for testability.
The answer, like most questions about practices, is "it depends".
Overuse of mocks can lead to tests that don't really test anything. It can also lead to tests which are virtual re-implementations of the code under test, tightly bound to a specific implementation.
On the other hand, judicious use of mocks and stubs can lead to unit tests which are neatly isolated and test one thing and one thing alone - which is a good thing.
It's all about moderation.
It makes sense to mock classes so tests can be written early in the development lifecycle.
There is a tendency to continue to use mock classes even when concrete implementations become available. There is also the tendency to develop against mock classes (and stubs) necessary early in a project when some parts of the system have not been built.
Once a piece of the system has been built it is necessary to test against it and continue to test against it (for regression). In this case starting with mocks is good but they should be discarded in favour of the implementation as soon as possible. I have seen projects struggle because different teams continue to develop against the behaviour of the mock rather than the implementation (once it is available).
By testing against mocks you are assuming that the mock is characteristic of the system. Often this involves guessing what the mocked component will do. If you have a specification of the system you are mocking then you don't have to guess, but often the 'as-built' system doesn't match the original specification due to practical considerations discovered during construction. Agile development projects assume this will always happen.
You then develop code that works with the mock. When it turns out that the mock does not truly represent the behaviour of the real as-built system (eg. latency issues not seen in the mock, resource and efficiency issues not seen in the mock, concurrency issues, performance issues etc) you then have a bunch of worthless mocking tests you must now maintain.
I consider the use of mocks to be valuable at the start of development but these mocks should not contribute to project coverage. It is best later if the mocks are removed and proper integration tests are created to replace them otherwise your system will not be getting tested for the variety of conditions which your mock did not simulate (or simulates incorrectly relative to the real system).
So, the question is whether or not to use mocks, it is a matter of when to use them and when to remove them.
It depends how often you use (or are forced by bad design) mocks.
If instantiating the object becomes too hard (and it happens more than often), then it is a sign the code may need some serious refactoring or change in design (builder? factory?).
When you mock everything you end up with tests that know everything about your implementation (white box testing). Your tests no longer document how to use the system - they are basically a mirror of its implementation.
And then comes potential code refactoring..
From my experience it's one of the biggest issues related to overmocking. It becomes painful and takes time, lots of it.
Some developers become fearful of refactoring their code knowing how long will it take.
There is also question of purpose - if everything is mocked, are we really testing the production code?
Mocks of course tend to violate DRY principle by duplicating code in two places: once in the production code and once in the tests.
Therefore, as I mentioned before, any change to code has to be made in two places (if tests aren't written well, it can be in more than that..).
Edit: Since you have clarified that your colleague meant mock class is bad but mock interface is not, the answer below is outdated. You should refer to this answer.
I am talking about mock and stub as defined by Martin Fowler, and I assume that's what your colleague meant, too.
Mocking is bad because it can lead to overspecification of tests. Use stub if possible and avoid mock.
Here's the diff between mock and stub (from the above article):
We can then use state verification on
the stub like this.
class OrderStateTester...
public void testOrderSendsMailIfUnfilled() {
Order order = new Order(TALISKER, 51);
MailServiceStub mailer = new MailServiceStub();
order.setMailer(mailer);
order.fill(warehouse);
assertEquals(1, mailer.numberSent());
}
Of course this is a very simple test -
only that a message has been sent.
We've not tested it was send to the
right person, or with the right
contents, but it will do to illustrate
the point.
Using mocks this test would look quite
different.
class OrderInteractionTester...
public void testOrderSendsMailIfUnfilled() {
Order order = new Order(TALISKER, 51);
Mock warehouse = mock(Warehouse.class);
Mock mailer = mock(MailService.class);
order.setMailer((MailService) mailer.proxy());
mailer.expects(once()).method("send");
warehouse.expects(once()).method("hasInventory")
.withAnyArguments()
.will(returnValue(false));
order.fill((Warehouse) warehouse.proxy());
}
}
In order to use state verification on the stub, I need to make some extra methods on the >stub to help with verification. As a result the stub implements MailService but adds extra >test methods.

Mocks or real classes? [duplicate]

This question already has answers here:
When should I mock?
(4 answers)
Closed 9 years ago.
Classes that use other classes (as members, or as arguments to methods) need instances that behave properly for unit test. If you have these classes available and they introduce no additional dependencies, isn't it better to use the real thing instead of a mock?
I say use real classes whenever you can.
I'm a big believer in expanding the boundaries of "unit" tests as much as possible. At this point they aren't really unit tests in the traditional sense, but rather just an automated regression suite for your application. I still practice TDD and write all my tests first, but my tests are a little bigger than most people's and my green-red-green cycles take a little longer. But now that I've been doing this for a little while I'm completely convinced that unit tests in the traditional sense aren't all they're cracked up to be.
In my experience writing a bunch of tiny unit tests ends up being an impediment to refactoring in the future. If I have a class A that uses B and I unit test it by mocking out B, when I decide to move some functionality from A to B or vice versa all of my tests and mocks have to change. Now if I have tests that verify that the end to end flow through the system works as expected then my tests actually help me to identify places where my refactorings might have caused a change in the external behavior of the system.
The bottom line is that mocks codify the contract of a particular class and often end up actually specifying some of the implementation details too. If you use mocks extensively throughout your test suite your code base ends up with a lot of extra inertia that will resist any future refactoring efforts.
It is fine to use the "real thing" as long as you have absolute control over the object. For example if you have an object that just has properties and accessors you're probably fine. If there is logic in the object you want to use, you could run into problems.
If a unit test for class a uses an instance of class b and an change introduced to b breaks b, then the tests for class a are also broken. This is where you can run into problems where as with a mock object you could always return the correct value. Using "the real thing" Can kind of convolute tests and hide the real problem.
Mocks can have downsides too, I think there is a balance with some mocks and some real objects you will have to find for yourself.
There is one really good reason why you want to use stubs/mocks instead of real classes. I.e. to make your unit test's (pure unit test) class under test isolated from everything else. This property is extremely useful and the benefits for keeping tests isolated are plentiful:
Tests run faster because they don't need to call the real class implementation. If the implementation is to run against file system or relational database then the tests will become sluggish. Slow tests make developers not run unit tests as often. If you're doing Test Driven Development then time hogging tests are together a devastating waste of developers time.
It will be easier to track down problems if the test is isolated to the class under test. In contrast to a system test it will be much more difficult to track down nasty bugs that are not apparently visible in stack traces or what not.
Tests are less fragile on changes done on external classes/interfaces because you're purely testing the class that is under test. Low fragility is also an indication of low coupling, which is a good software engineering.
You're testing against external behaviour of a class rather than the internal implementation which is more useful when deciding code design.
Now if you want to use real class in your test, that's fine but then it is NOT a unit test. You're doing a integration test instead, which is useful for the purpose of validating requirements and overall sanity check. Integration tests are not run as often as unit tests, in practice it is mostly done before committing to favorite code repository, but is equally important.
The only thing you need to have in mind is the following:
Mocks and stubs are for unit tests.
Real classes are for integration/system tests.
Extracted and extended from an answer of mine How do I unit-test inheriting objects?">here:
You should always use real objects where possible.
You should only use mock objects if the real objects do something you dont want to set up (like use sockets, serial ports, get user input, retrieve bulky data etc). Essentially, mock objects are for when the estimated effort to implement and maintain a test using a real object is greater than that to implement and maintain a test using a mock object.
I dont buy into the "dependant test failure" argument. If a test fails because a depended-on class broke, the test did exactly what it should have done. This is not a smell! If a depended-on interface changes, I want to know!
Highly mocked testing environments are very high-maintenance, particularly early in a project when interfaces are in flux. Ive always found it better to start integration testing ASAP.
I always use a mock version of a dependency if the dependency accesses an external system like a database or web service.
If that isn't the case, then it depends on the complexity of the two objects. Testing the object under test with the real dependency is essentially multiplying the two sets of complexities. Mocking out the dependency lets me isolate the object under test. If either object is reasonably simple, then the combined complexity is still workable and I don't need a mock version.
As others have said, defining an interface on the dependency and injecting it into the object under test makes it much easier to mock out.
Personally, I'm undecided about whether it's worth it to use strict mocks and validate every call to the dependency. I usually do, but it's mostly habit.
You may also find these related questions helpful:
What is object mocking and when do I need it?
When should I mock?
How are mocks meant to be used?
And perhaps even, Is it just me, or are interfaces overused?
Use the real thing only if it has been unit tested itself first. If it introduces dependencies that prevent that (circular dependencies or if it requires certain other measures to be in place first) then use a 'mock' class (typically referred to as a "stub" object).
If your 'real things' are simply value objects like JavaBeans then thats fine.
For anything more complex I would worry as mocks generated from mocking frameworks can be given precise expectations about how they will be used e.g. the number of methods called, the precise sequence and the parameters expected each time. Your real objects cannot do this for you so you risk losing depth in your tests.
I've been very leery of mocked objects since I've been bitten by them a number of times. They're great when you want isolated unit tests, but they have a couple of issues. The major issue is that if the Order class needs a a collection of OrderItem objects and you mock them, it's almost impossible to verify that the behavior of of the mocked OrderItem class matches the real-world example (duplicating the methods with appropriate signatures is generally not enough). More than once I've seen systems fail because the mocked classes don't match the real ones and there weren't enough integration tests in place to catch the edge cases.
I generally program in dynamic languages and I prefer merely overriding the specific methods which are problematic. Unfortunately, this is sometimes hard to do in static languages. The downside of this approach is that you're using integration tests rather than unit tests and bugs are sometimes harder to track down. The upside is that you're using the actual code that is written, rather than a mocked version of that code.
If you don't care for verifying expectations on how your UnitUnderTest should interact with the Thing, and interactions with the RealThing have no other side-effects (or you can mock these away) then it is in my opinion perfectly fine to just let your UnitUnderTest use the RealThing.
That the test then covers more of your code base is a bonus.
I generally find it is easy to tell when I should use a ThingMock instead of a RealThing:
When I want to verify expectations in the interaction with the Thing.
When using the RealThing would bring unwanted side-effects.
Or when the RealThing is simply too hard/troublesome to use in a test setting.
If you write your code in terms of interfaces, then unit testing becomes a joy because you can simply inject a fake version of any class into the class you are testing.
For example, if your database server is down for whatever reason, you can still conduct unit testing by writing a fake data access class that contains some cooked data stored in memory in a hash map or something.
It depends on your coding style, what you are doing, your experience and other things.
Given all that, there's nothing stopping you from using both.
I know I use the term unit test way too often. Much of what I do might be better called integration test, but better still is to just think of it as testing.
So I suggest using all the testing techniques where they fit. The overall aim being to test well, take little time doing it and personally have a solid feeling that it's right.
Having said that, depending on how you program, you might want to consider using techniques (like interfaces) that make mocking less intrusive a bit more often. But don't use Interfaces and injection where it's wrong. Also if the mock needs to be fairly complex there is probably less reason to use it. (You can see a lot of good guidance, in the answers here, to what fits when.)
Put another way: No answer works always. Keep your wits about you, observe what works what doesn't and why.