.NET mocking frameworks, a comparison
codetuple.com
codetuple.com
After reading this article, did you know that FakeItEasy is very slow, so is unsuitable for fuzz testing? Or that NSubstitute can't mock statics, but Microsoft Moles (absent from this list) can?
I do, because I had a developer in my team do that investigation before we decided to standardise our unit testing stack.
I can't review the decision yet because we were been forced to cut our investment in unit testing, instead focusing on Selenium tests (sigh, "management" should know better).
WRT FakeItEasy - we also found that it's not thread safe. Using it with XUnit (XBehave) we had to explicitly tell Xunit to run tests sequentially.
Notable in absence in addition to Moles is Machine.Fakes.
The idea is that you don't need to learn yet another domain specific language just to do some assertions on mock call history. So I expose it all as plain old C# data, LINQ'able and all that, which means you can just use the assertion library of choice instead of weird mock-library-specific "verify" methods. The API gets you great autocomplete in IDEs because of static typing, so you discover the API just by starting to type.
Intellisense-driven discoverability of APIs is one of the great USPs of C# and Java programming (compared to most other popular languages), and IMO it's a shame that more TDD related libraries don't make good use of it.
It's not under active development but I'd be willing to take it up again if there's interest. Would love some HN feedback!
My understanding of mocking by example is: you have a class you want to test, and that class has a dependency on lets say a Mail class that has a SendMail() method. You mock the Mail class and assert that SendMail() was called as per your specification.
Given that definition of mocking, I personally don't like mocking. I prefer to test state not behavior, although I can see in some scenarios behavior is more important.
In short yea, you're right.
Mocking libraries create dummy objects. They can't reproduce inner workings of mocked object unless you set it up to behave like that, which means you should duplicate the original which is pointless. You set up the mock to listen on it's entry points (and to return some predetermined answer), give it to your code under test, and expect the mock to be called in a certain way. This is testing the entry point of the mocked object, not it's internal workings. This way, you're expecting the code under test to behave according to a definition, so you're still testing your code, the way it's calling some other object gives you insights of your code's inner workings.
Stubs return canned data. This is great for testing that the calculations in your unit are correct without having to use the real collaborators. With stubs you are saying, "I expect my unit to produce this output from this input".
Fakes are objects that provide a working interface for your unit and often provide either stubs or mocks. It is not quite correct (IMHO) to say that a fake can be a stub or it can be a mock. It may also be used when you have highly coupled code and you just need the object that does intelligent things so that you can get to the meat of your test. This is a very common technique when you are trying to inject tests into legacy code. With a fake you are saying "I need to use a working collaborator, but I don't want to use the real collaborator for some reason" (usually because it is slow/dangerous/hard to create).
Like I said, fakes often contain/return stubs or mocks. A good example of a fake would be a fake that implemented a REST interface and returned canned data depending on what parameters you sent it. It would replace the exact same object with a REST interface that would be used to talk to the network.
I wonder if this secondary(?) meaning of "mock" is an argot more common among some programming languages/communities than others, because the meaning that comes to mind most readily when I see "mock" is "to treat with contempt or ridicule".
Rolling my own might take fractionally more effort to initially set up but the transparency of what happens and ability to debug through to me is of more value.
var authenticationService = Substitute.For<IAuthenticationService>();
authenticationService.Authenticate("goofy").Returns(true);
authenticationService.Authenticate("Donald duck").Returns(false);
In another test I can easily create a mock that returns true regardless of the users to go on with testing other parts of the code.
In your case you need to create two concrete objects that will have a different behaviour.
And what if you need a test that checks that users with some roles need to be authorized?
And other members of your team need to search for an existing manual mock otherwise they may end adding some utterly useless duplicated manual mock, and in big teams you can see that it can be easily a huge mess.
If you are the only person to write code it's up to you to waste your time, but in a shared codebase you need to be mindful of other people.E.g. NSubsittue is here: http://nsubstitute.github.io/
FakeItEasy is here: https://fakeiteasy.github.io/
And even though it's commercial product, one should mention TypeMock.