nsubstitute/NSubstitute

How to name a satellite nuget package designed to work with NSubstitute?

fluffynuts opened this issue · 7 comments

Question

I've been using NSubstitute for a very long time - it's how I was introduced to mocking in .NET, as part of TDD practices. As part of my current work, I often have the duty to work in an area with really old code where Moq has been used and I prefer to keep things consistent, so I convert the code. All good.

One of the more common patterns I see in the code I'm cleaning up is the ability of Moq to set up a bunch of mocked methods and then call .VerifyAll() on the mock at the end, testing that everything that was set up was used as expected. It saves some coding time and repetition at the cost of not being immediately obvious (the reader has to scroll up to the setup - hopefully it's just a scroll-up, and not having to look in a file elsewhere) to see what is being verified. However, when there's a lot of stubbing done for a test, .VerifyAll() can reduce some assertion noise. So it feels like a balance.

At any rate, when converting a project, I already have to modify the stub setup and then re-create very similar code to assert that the stubs were called as expected, so I've written a simple .VerifyAll() to try out in the project I'm currently upgrading (netfx -> dotnet) and published as a beta package with a really stupid name because the NSubstitute prefix has been reserved on nuget.org - as well as, apparently, some other names, because I was unable to publish any of the following:

  • NSubstitute.VerifyAll (the obvious, searchable choice)
  • NSubstitute-VerifyAll
  • VerifyAll4NSubstitute
  • VerifyAll.NSubstitute
  • VerifyAll

I can continue testing with my badly named package, which is beta anyway, so it shouldn't easily show up in search results, but I'd really like to call it something that others might be able to find easily, so I'm up for suggestions:

  1. What name would be obvious and searchable without being in the above list? or
  2. How do I get permission to publish NSubstitute.VerifyAll ?

Hi @fluffynuts , that's great to hear! Thanks for raising the question.
Yes, NSubstitute prefix is protected and reserved for NSubstitute packages but we opened NSubstitute.Community.* for such contributions. You should be able to push your package as NSubstitute.Community.VerifyAll. Let me know if it doesn't work.

On a side note, I haven't really used VerifyAll() in my experience. Is it helpful only when porting from Moq? Do people use it on its own? Do you think it make sense to port it to NSubstitute?

I need to preface with a reminder that I'm not a moq pro, but:

Moq adds methods for mocks:

  • Verifiable
  • Verify
  • VerifyAll

The first two are related - by adding .Verifiable() to the end of the setup line for a method, one can later call .Verify() on the mocked object to verify that all the mocks which had .Verify() applied were called as intended (though I'm not sure about setting call limits, and I try to be very specific about that.

.VerifyAll() does the same, but for all mocked members, irrespective of whether or not they were marked .Verifiable()

Now, in the case where there's perhaps 1 or 2 mocked methods and we'd like to assert that they were called appropriately, I'd prefer to set up at the top of the test and assert later, and a lot of that code will be very similar, but that's fine for the simpler case. But if there's a lot that's been mocked, individual assertions on each method can become a lot like repeated noise. Enter .VerifyAll(), which sacrifices the locality of the assertion for convenience, stating "just check that this sub was called as it was set up".

Personally, I don't see the benefit of .Verify() and .Verifiable() - I'd rather make my own assertions than make the reader scroll up to find out what is being verified. At least with .VerifyAll(), the answer to that question is "all of it" 😂 Whilst convenience certainly is a good reason to use my extension, right now I want to make the fewest changes possible to these tests whilst upgrading, so if I can make minor changes on the setup and uage, and leave verification alone, that's a win. So for a Moq-to-NSubstitute conversion, it could be really useful, depending, of course, on how the tests were originally written.

Would something like .VerifyAll() work well in core NSubstitute? I think so, but I still need to prove that my hack even works before going any further. The tests work, but I haven't had any major usage and won't have a building, running test project for a while as I still have lots to fix up there from the NUnit upgrade (this project is being dragged into the current age 🤣). If it ends up working nicely, I'll revisit this - right now, it's a reflective hack, so it could be a lot less brittle and trashy.

Thanks for the name idea - I'll go get a beta package out to at least reserve it and will report back when I have more conclusive evidence that what I've done was even worth doing.

as a side-note, there probably has to be some kind of debate as to what expectations would be for .VerifyAll() - so I'm leaving this here to ponder:

  1. .VerifyAll() should verify that the set up methods are called with the exact arguments they were set up with. Any extra calls or missing calls constitutes failure. This is the route I've gone -- stricter rather than looser.
  2. However, someone may say that a looser interpretation could follow, eg:
    a. verify not necessarily that all the mocks were called, but that all the calls that were received were set up (so there may be extraneous setup, but this could be a common mock?)
    b. verify that all the mocks were called as set up, but also allow methods which weren't set up to proceed without error

The stricter case makes more sense to me, but that may just be a personal preference.