Mocking Methods: Out and Ref Parameters
A free video tutorial from Dmitri Nesteruk
Software/Hardware Engineering • Quant Finance • Algotrading
4.4 instructor rating • 21 courses • 159,011 students
It's also possible to mock methods that have ref or out parameters, sometimes with surprising results.
Learn more from the full courseMaster .NET and C# Unit Testing with NUnit and Moq
Become an expert in unit testing with NUnit, Moq, dotMemoryUnit, ReSharper and other tools!
03:13:23 of on-demand video • Updated August 2017
- What unit tests are for and how they are written
- How to set up and use the NUnit test framework
- What are the different test doubles: fakes, stubs, mocks
- How to effectively use the Moq mocking framework
- How to use the ReSharper unit test runner
- How to write memory-related unit tests using dotMemoryUnit
English [Auto] Now let's talk about what happens if your Malke object tasked to perform particular behavior with respect to ref arguments or out arguments. So here in the Eiffel interface I have a method which has a ref argument and also method which has an out argument. So we're going to see how we can actually control the behavior of these methods with reference to arguments respectively. So once again I'll make them all object like so and we'll start with all the arguments. So for example I can specify the kind of required output that I want. Given a particular invocation of try parse so try parse ticks a string it has an outer string output value and I can specify that the output value I want should be the string. Ok so I can say var required output equals. OK OK. So this is a string that I want returned from the method. Whenever somebody calls this method on our mark object. So here what I would do is I would say mawk Daut set up and I would say foo goes to food Daut try parce. So that's the method that we actually want to configure. So whenever somebody calls it with let's say the first argument being equal to ping I can then say that the output is going to be required outputs. So notice that even though I'm using the out key word here for required output it's actually smarter than that in the sense that it figures out that you want this string to be returned from the method no. Verify this in just a second. So here I can say for example that we're going to return true. In this particular case and then we can call this Malke object and we can assert on our expectations. So we need a string to hold the result obviously. And now we need to do two things. So once again I'm going to send multiple here. Let's have a lambda. So first of all I want to make sure that well actually I want to make sure that we get the value of true. First. And that can be combined with the actual invocation so I'm going to assert that is true. And then I'll take the mock object and call the method on it. So don't do something. Let's try Parus actually and it has to be on the object not on the market self so marked object don't try parse. We specify the value of paying and we have a bunch of expectations. So here I specify out result. So the first expectation is that with the value of paying I expect the result to be true. And that's what I'm asserting on. And the second thing I'm going to assert is that the result we got is the same as the required output the same as what we've configured the system with. So here I will put in an other assertion assert that and I will assert that the result is equal to the required output. OK let's see if these assumptions actually hold. Excellent. So as you can see it works and by the way just in case you're wondering the highlighting that we saw on the required out the being needed by resharpen is just a spurious thing you shouldn't really worry about it. Now you're probably wondering what would happen if you actually were to call try Parr's with a different argument something other than ping. Now typically this gives fairly unpredictable results because you haven't configured the actual object. So we can try this. We can actually save var. This should be false. And we can do marked out object. Try parce so we can provide pong instead of paying and we can't do out result once again. And then we can do a few assertions just to see what's going on. So instead of assertions Actually let's do consolidate right line so I'm going to write line both. This should be false as well as the result. So that's right line the result. Luckily we shoppers test run their outputs. Anything that you write to the console right as part of the unit test session so we're going to see it on the right and as you can see if we get the values of Folse But we also get OK. So interestingly enough even though we haven't configured this particular case to return OK it still returns OK. So I guess the takeaway from this is you have to be careful even though you never asked for pong to return the result of OK the mock framework still did it anyway. So these are the out parameters and how you can work with them. Next up let's talk about the ref arguments. So we look up here we have a method called the where is it. Submit. Which takes a ref bar. So let's take a look at how we can actually mock this whole thing and get it working. So I'll make a bar I'll just construct an empty bar to begin with. And then we can set up the mark once again. So here I can say mulct set top. And here I say that whenever somebody calls submit. So whenever somebody says food submit this minute and I'll put the bar in here we have to return true. OK. Now here's where things get interesting because suddenly I can assert that if somebody does in fact call Malke with this bar I should get the value. True. It makes sense. So if I say Malke dot object dot submit with ref bar I should get true. So let's check it equal to true. So let's actually run this to see that it does in fact work. And then we'll take a look at something else. So we succeed so far. If I make a different bar. So if I make a different object of our let's call it some other bar bar bar like so then we can assume it is false. So we can no longer require it or we can no longer expect it to return true. And by default boolean returns false so we can assert that if you feed this particular object into submit it's going to return false. Mark don't object. Submit some other bar. There we go. OK. So having done this with the ref key word we can once again run the tests and see that it still works. So our expectations are still being upheld and as you can see that's exactly what happens. Now I do have a piece of bad news somewhat and that is to do with the kind of equality comparisons that the mock framework actually uses when it compares the different bar object. So let me show you something that you can do on bar to maybe get some intuitive behavior out of it. So let's suppose for example that we give bar a property public string name get set for example and we can also generate all the quality members. Literally everything that resharpen can throw at us. So let's do a quality members I'll compare on bar and they'll generate just about everything that you can generate. So now the bar is equatable and it has this property called name here. You might be expected to think that if this bar and this bar have the same name then everything is fine. And we're going to actually get them to match so to speak but unfortunately this doesn't happen. So if I say name he calls ABC here and then I go ahead and I see say name he calls ABC here if I run these tests now I may actually go down here if I run these tests. Unfortunately all of these tests still pass all of these tests are still green. Now why is it unfortunate you might ask. Well strictly speaking you might expect mulk framework to basically recognize that as you've said it up with the bar here you've provided an identical bar here in terms of their equate ability and so on. So why is it false. So that's the question. And unfortunately the take away is that Malke does referential comparisons. It compares the actual references it uses reference equals or whatever so it's going to use the equatable interface or any kind of smart comparison to actually figure out that these are the same object. It's still going to just look at them as purely references.