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.
Mock - an object on which you set expectations. Fake - an object with limited capabilities (for the purposes of testing), e.g. a fake web service. Test Double is the general term for stubs, mocks and fakes. But informally, you'll often hear people simply call them mocks.
Fakes are generally used to improve performance by avoiding external calls. Mocks are used to verify the behavior of our code. Stubs are used to provide data that our code needs to run. We should use the simplest test double that will get the job done.
Only use a mock (or test double) “when testing things that cross the dependency inversion boundaries of the system” (per Bob Martin). If I truly need a test double, I go to the highest level in the class hierarchy diagram above that will get the job done. In other words, don't use a mock if a spy will do.
The benefits of a mocking framework are: Easier (subjective, but after a while you will not write hand written implementations) Less Code (frameworks allow you to create a mock in a matter of lines, rather than full class declarations) Follows DRY (you won't end up repeating mock implementations)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With