When to use mocking versus faking in C# unit testing?
Can anyone come up with guidelines suggesting the ideal scenarios to choose mocking versus faking, i.e., setting up the essentials manually?
I am a bit confused with how to approach this situation.
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() { //Arrange Mock<ITaxRateDataAccess> taxDALMock = new Mock<ITaxRateDataAccess>(); taxDALMock.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001")) .Returns(0.08).Verifiable(); TaxCalculator calc = new TaxCalculator(taxDALMock.Object); //Act decimal result = calc.CalculateTax("75001", 100.00); //Assert 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() { //Arrange Mock<ITaxRateDataAccess> taxDALStub = new Mock<ITaxRateDataAccess>(); taxDALStub.Setup(taxDAL => taxDAL.GetTaxRateForZipCode("75001")) .Returns(0.08); TaxCalculator calc = new TaxCalculator(taxDALStub.Object); //Act decimal result = calc.CalculateTax("75001", 100.00); //Assert 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.
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
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.
The Little Mocker, from Bob Martin, is a very good reading on the topic.
[...] long ago some very smart people wrote a paper that introduced and defined the term Mock Object. Lots of other people read it and started using that term. Other people, who hadn't read the paper, heard the term and started using it with a broader meaning. They even turned the word into a verb. They'd say, "Let's mock that object out.", or "We've got a lot of mocking to do."
The article explains the differences between mocks, fakes, spys and stubs.