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.