views:

443

answers:

4

Can anyone come up with a guidelines kind of stuff, suggesting the ideal scenarios when to go for mocking or faking (setting up the essentials manually). Bit confused with the approach?

+1  A: 

You want to test a chunk of code, right, let's say a method. Your method downloads a file from a http url, and then saves the file on disk, and then mail out that the file is on disk. All these three actions are of course service-classes your method calls, because then they are easy to mock. If you don't mock these, your test will download stuff, access the disk, and mail a message every time you run that test. Then you are not just testing the code in the method, you are also testing the code that downloads, writes to disk and sends a mail. Now if you are mocking these, you are testing just the methods code. Also you are able to simulate a download failure for instance, to see that your method's code is behaving correctly.

Now as for faking, I usually fake classes that are just holding values, and don't have much logic. If you are sending in an object that holds some values, that get changed in the method, you can read off of it in the test to see that the method do the right thing.

Of course the rules can (and sometimes must) be bent a bit, but the general way of thinking is test your code, and your code only.

crunchdog
+20  A: 

Well you have a few things you need to sort out. You have two basic things you'll need to know: Nomenclature and Best Practices.

First I want to give you a great video resource from a great tester, Roy Osherove:

Unit Testing Reviews by Roy Osherove

He starts out by saying that he has done some reviews of test harnesses shipped with several open source projects. You can find those here: http://weblogs.asp.net/rosherove/archive/tags/TestReview/default.aspx

These are basically video reviews where he walks you through these test harnesses and tells you what is good and what is bad. Very helpful.

Roy also has a book that I understand is very good.

Nomenclature

This podcast will help out immensely: http://www.hanselminutes.com/default.aspx?showID=187

I'll paraphrase the podcast, though (that Hanselminutes intro music is dreadful):

Basically everything you do with an isolation framework (like Moq, Rhino Mocks, Type Mock, etc) is called a Fake.

A Fake is an object in use during a test that the code you are testing can call in place of production code. A fake is used to isolate the code you are trying to test from other parts of your application.

There are (mainly) two types of fakes: Stubs and Mocks.

A Mock is a fake that you put in place so that the code you are testing can call out to it and you assert that the call was made with the correct parameters. The below sample does just this using the Moq isolation framework:

[TestMethod]
public void CalculateTax_ValidTaxRate_DALCallIsCorrect()
{
    Mock<ITaxRateDataAccess> taxDALMock = new Mock<ITaxRateDataAccess>();
    taxDALMock.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001"))
                  .Returns(0.08).Verifiable();

    TaxCalculator calc = new TaxCalculator(taxDALMock.Object);
    decimal result = calc.CalculateTax("75001", 100.00);
    taxDALMock.VerifyAll();
}

A Stub is almost the same as a mock, except that you put it in place to make sure the code you are testing gets back consistent data from its call (for instance, if your code calls a data access layer, a stub would return back fake data), but you don’t assert against the stub itself. That is, you don’t care to verify that the method called your fake data access layer – you are trying to test something else. You provide the stub to get the method you are trying to test to work in isolation.

Here’s an example with a stub:

[TestMethod]
public void CalculateTax_ValidTaxRate_TaxValueIsCorrect()
{    
    Mock<ITaxRateDataAccess> taxDALStub = new Mock<ITaxRateDataAccess>();
    taxDALStub.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001"))
                  .Returns(0.08);

    TaxCalculator calc = new TaxCalculator(taxDALStub.Object); 

    decimal result = calc.CalculateTax("75001", 100.00);
    Assert.AreEqual(result, 8.00);
}

Notice here that we are testing the output of the method, rather than the fact that the method made a call to another resource.

Moq doesn’t really make an API distinction between a Mock and a stub (notice both were declared as Mock<T>), but the usage here is important in determining the type.

Hope this helps set you straight.

Anderson Imes
Ayende (creator of Rhino Mocks) recently announced that he's going to ditch the Mock vs Stub and just make everything a Fake in the next version of Rhino Mocks. Some would argue that you gain more knowledge knowing that something is a Stub instead of a Mock, but that's getting a bit nit picky. If you don't care, just use Mocks all the time and don't assert their assumptions. It'll save you some headache of having to figure out which to use.
Kevin Pang
Very good explanation Anderson. I am not familiar with fakes or faking, but am familiar with Mocking and Stubs. The fake nomenclature comes from where?
Ty
@Anderson Imes Sorry I wasn't more explicit. I understand your description and it is quite sufficient. What I mean is who came up with the nomenclature for "Fakes". I've never see it mentioned in this context before and everything I have read has always been Mocks vs Stubs. I also subscribe to Ayende's blog, but have never seen him mention Mocks/Stubs and Fakes in the same sentence.
Ty
@Anderson Imes Nvm, you answered it by the link switch I rushed past. Hanselman is the culprit here :)
Ty
couple of downvotes.... any downvoters want to tell me how I can improve this?
Anderson Imes
+1 I don't know how i missed this question, but this is a great explanation.
Ahmad
+1  A: 

If you can wait another month, our book will be out where we go into this at length. In the meantime, there's some preview material at http://www.mockobjects.com/book

Steve Freeman
@ steve OUR BOOK , sounds gr8 have u contributed to the book.?
vijaysylvester
I'm a co-author.
Steve Freeman
+6  A: 

There are at leat 5 different kinds of test doubles: dummies, stubs, mocks, spies and fakes. A good overview is at http://code.google.com/testing/TotT-2008-06-12.pdf and they are also categorized at http://xunitpatterns.com/Mocks,%20Fakes,%20Stubs%20and%20Dummies.html

Esko Luontola
Wow... really nice resource. That xUnit link goes a long way to showing just how much our industry is making this crap up as we go along.
Anderson Imes