 On today's Visual Studio Toolbox, we'll take a look at another important piece of the unit testing world and that is Mox. Hi, welcome to Visual Studio Toolbox. I'm your host Robert Green. Joining me is Phil Jepixi. Hey, Robert. Hey, Phil. This is episode three of our series on unit testing. We did an overview and looked at test driven development. We looked at X unit and today mock you. Mock you. Which is not a slur. I'm not making fun of you. Not something you say to people. Right. But it is a framework to create mocks or stand ins, if you will, for dependencies in your code that don't affect the test. Okay. So in other words, you're calling a database or you're calling a service somewhere and you're testing not the invocation of that service, but you're testing what happens after you successfully complete the call to that and it sends you something back. Yeah. So to put it in my mind clearer, I have a controller that's going to return a view with a list of customers. So I have an I repo that I'm injecting in through dependency injection into that controller and I repo isn't going to call the database to get the customers back. Right. Well, my logic in the action method of the controller is independent of the actions of the repo. It needs the result of that call doesn't care how it does the call. Right. So what I want to do is not risk my test failing or my controller failing because the database is down. But I want to put a stand in or a replacement for the I repo that I can also control. So I can set it up with an expectation that when the repo is called to get all, it returns zero. How does my controller behave? Right. I want to return a thousand. How does my controller behave? And I can do all that independent of talking to a database. Are mocks the same as fakes? So no. But yes. So there's fake stubs and mocks and a lot of it is academic stubs and mocks. It's more of an academic distinction. But a fake is a stand in. So if I was using a fake, then I'm actually creating a concrete implementation of I repo that behaves a certain way. Right. And I can pass that in. And I can create a fake that returns no records. I can create a fake that returns a thousand records. But now I have two classes. And I have to create a new class for every scenario I want to test. So the problem with fakes is you're exponentially might be too strong of a word, but you're significantly increasing the amount of code you're writing to test your different scenarios. Right. So when I said yes and no, it is a stand in for the line of business application. But mocks and stubs are actually proxies around those things that you can set up expectations on. Okay. Now a stub and a mock. We use them pretty much interchangeably. The main difference are both proxies. But a mock, you can set up an expectation. So for example, I can say you need to call get customers on this mock, but only call it once. Right. And we can set up the mock to report that and record that and then throw an exception if it's called twice, for example. Whereas a stub is just a proxy without that behavioral set up capabilities. But honestly, that's academic. We don't really deal with the difference between stubs and mocks anymore. It's just a proxy that we can choose to behave a certain way. Okay. Cool. So we're going to get into the details here. And I just for a sake of time, again, all the samples are already coded. They're available in my GitHub repo. The link is in the show notes. And we'll have all that out to you. And the very simple example is I have, well, let's look at the system under test. So I have this I repo. And I have a controller, if we look at our test controller, it takes an instance of I repo and potentially an instance of I logger. So I can't even construct a controller without passing in at least an instance of I repo. Okay. So if I didn't have a fake, I can't even do new controller. I have to pass something in. So what we do is we create a mock of the I repo. This builds tell us where you got Oh, yes, I'll be back up. The toolbox part of this by going to manage new get packages. And look at what's installed. It is literally a project called moq. And most people, yes, package, sorry package, got it. Most people call it mock you moq, mock. There's some debate as to the pronunciation. I'm sure your readers have all kinds of comments about the pronunciation. The end of the day, it's the moq framework. Okay. And I am using it in conjunction with x unit, which we covered on the last episode. Okay. The way we create a mock around something very simply is we say, you know, of our mock equals new mock of I repo. Now you can mock concrete classes, but there's all kinds of caveats to that. What we really want to do is code to an interface in our line of business code. And it also makes it easier to mock because interfaces are infinitely mockable. So I have this proxy wrapping the I repo. And then I call setup. I said, if the find method gets called with the ID of 12 as the parameter, I'm going to return this customer. So now I have a controller that requires in the constructor an instance of I repo find method of what? Sorry, find method of what Oh, the find method of the I repo. Okay. So let's look at the I repo real quick. It's a just trimmed down repository pattern for data access. I've got a find I've got get some I've got add record. And I've got some event handlers for the advance examples only show later. So the find method of the I repo definition, which exists on the proxy that is created around the I repo, if that's called with a 12, it'll return this customer instance. Okay. So equivalent would be not using a mock. I put a real repo in there. When 12 is called, there darn well better be a customer in the database with the ID of 12, whose name is Fred Flintstone. Otherwise, his test will fail. Right. So I have my controller, we call market dot object that actually gets the instance of the I repo. And then I'm calling a method on the system under test, which is the controller, the repo is just carefully right so everything up to here is a range code. I have one action where I say get customer. And then there's my assertion that what the get customer call does is just calls repo dot fight. So then I test that. Yep, I'm actually getting this customer by calling get customer. And I'm asserting that the controller action method is behaving as I expected to. Now it might be annoying to set up a whole bunch of mock instances, but one of the nice things that Moq or Machu allows us to do is set up repetitive calls. So I'm going to call get customer twice. Instead of having to set up to all that arrange, do my action, do my range, do my action. I can set up a sequence, as opposed to setup, where if I call find, it returns this customer instance returns that customer instance. Now, I said earlier that everybody pretty much agrees you should only have one action in your test. I have two actions, technically, because I'm calling get customer twice. But what I would argue then is that this first call to get customer is my setup. I'm still arranging because what I'm testing is that my second call to get customer gets a different customer. So before people go, hey, there's two actions in there. It's a test scenario, right? So we can do it however we want. Any questions on the basics? The other thing that we want to do is we want to verify the behavior that our system under test is doing to the Mach. I had a customer once that called me down. They were having terrible performance. Every time they turned this feature on, it shut down their data center, right? Just crushed their databases. Turns out they had a loop where they're looping through all of their customers. And then calling all of the available products this company had to see which customers had those products, which customers didn't have those products. So they could basically build a call list, right? Hey, call Robert, he has product A, but he doesn't have product B, do a suggestive sell. Well, the way they actually did it was they built a list of their products. And as they looped through the list of products, they were calling the list of customers to get the list of customers to then call into the list of products that the customers had. Basically, they were calling get all customers for every single product squared. And in a test database, it worked fine. Right. In integration, it worked okay. Then they went to production, and this company has millions of customers. It shut down the data center. So I literally set up some mocks around their function calls and learned that they were calling get all customers 4,000 times or whatever as opposed to just once, which is what they should have been doing. So we want to verify the behavior, right? This is a there's between a stub and a mock. What we can do when we set up a call, we say it's verifiable. We want to track that this is called. And then later we can actually call mock dot verify that particular call to make sure behaved the system under test behaved as it should have. Okay. Now what if it's supposed to execute twice? The verify call has the ability to say it should execute exactly twice. Or once there's some overloads. Or what if we say, you know what, it should never call this method. And why would you want to test that? Well, let's look at our system under test again. And we should never call logger dot error unless there was an exception. So we could pass in an instance of I logger, right? A mock of that and say the call to error should never be called in this particular test. Right. So we've got incredible power with verifying how the mock behaves. We can also say verify all, which has make sure everything behaved the way it should. What we lose with that is the ability to say this should be called seven times it should be called never those types of things. Okay. But you can verify all of it. And we can also verify that they weren't executed, right? So what happens here is I am using this is an ugly test, but I was trying to show the feature within mock you as opposed to write a real test around the system. Okay. Right. So I'm saying the error message and this is what I was just talking about, right, the log error should never be called, right, we should never get to that logging message when we call find, right. And so this, you know what, let's just do the Jedi mind trick. You didn't see that test. This is really me writing a test to show how the framework works. What I want our viewers to focus on is this type of testing right here, where I am setting up, I just set up an expression so I don't have to repeat code, where I'm going to call find on the repo, make sure it executes only once. Because our controller itself, let's actually look at that. If I go in this controller and make a mistake where I say, this will still work, right, from the outside perspective, I'm still getting the customer back. But I've now done these 12 calls to database, which is going to crash my performance. Right. So now I can verify that I'm only calling it once. And that test will fail. Okay. Now, your viewers are smart enough not to do that. But what might happen is they call find up here. And then you've got 20 some lines of code of other stuff. And then you're like, Oh, I'm just going to return repo dot find, right, right. So it's usually buried in there. And so you can verify it that way. Does that make sense? Yeah. All right. My mouse just went to sleep. Well, it's awake. It's a surface mouse. It should be better. Let's talk about arguments. When we set up a mock and an expectation on the mock, we can set up to be very specific to a parameter. Or we can say we don't care about the parameter. Okay. We look at this first test here. I am saying return the customer if 12 is passed into the find method. If anything else is passed in, it's going to return null. Okay. So then when I call, get customer, but I'm actually passing in 13. I don't get a customer back. Right. So sometimes you care what the value is is getting passed in. But sometimes you don't care. So we can say any integer, if any integer is passed into the find method, return to customer. Okay. I don't care. If you pass in seven, seven million, doesn't matter, still return a customer. I just want to make sure that we're calling this find method once. And then we're getting a customer back. And that the controller that is returning that customer. And there's some other syntax you can use. You can also use is in range and things like that. So very powerful how you set it up. I will tell you that I almost always will do it. Is any string things like that, unless I'm looking for a very specific behavior where the parameter matters. Okay. A lot of times when I'm testing my systems under test, I don't care about the parameter. Right. I'm checking the behavior. We also have the ability to do what's what I refer to as a rolling mock, probably not the official name, but it works for me. What I have here is again showing off X unit, which we explained in the last show. Yes, we did. And I have inline data. And then what I have is a list of customers. Now, this is different than setting up a sequence. This is the ability to call returns multiple times. And then it's going to return not a single customer, but it's going to return based on the nth time it was called that customer in the list. So you can customize the returns, even though the I repo returns a customer, I'm still returning a customer here, but we're inserting an action, sorry, we're inserting a funk to control how that works. So this might be an important thing to know if your method your system under test is going to call find multiple times intentionally, and it's going to iterate through until it finds a certain record, like, Hey, I want the seventh customer that is active. And you want to test that behavior, you can do it this way. Okay. So you get more power with that. And then the last major thing I want to cover from a mocking of a repo is mocking events. Because that's something that is traditionally very hard to test. Like without setting up a mock, how would you test it an event was fired, and make sure that that method that the was called by the event was actually executed. Well, we use a combination of everything we've talked about so far, and that we've got the mock repo. Now we're pulling in the mock I logger. And we're setting up the expression where we're calling the error. Now what raises the event is the I repo. So we set up an expectation. And we actually use the term raise. So the mock repo, this proxy around the I repo, will raise the event fail database event. And we can customize it pass in its instance event args. If you have a custom event handler, you can customize it. I didn't go in that great detail. The documentation is actually pretty good. So that the repo will raise this event. And what we're verifying here is that the logger calls the error function. Now let's walk through the system under test. So the repo calls find. What we want the repo to then raise is the failed database request, which is then handled by this event handler, which calls logger dot error. So in one test, I'm making sure that the controller not only has wired up the event handler for that event, but it's also logging that error correctly. And without using a mock framework, I'm not even sure how I'd go about testing this. Yeah, like about using a fake. We can also set up an event to be raised after some action is done. So for example, here, instead of calling just raise, I'm setting up that when add record is called, then the event gets raised. And this is more appropriate for real life testing. What happens in this prior test is as soon as I call mock repo dot raise that event gets raised. Okay. But in reality, we want the event to be raised based on an action of the system under test, which is how real life works. So I am setting up that when add record is called on the repo, then I raise the event. Okay. So now we're getting into the real life timing. So I go back into my controller. And they call add record, which is here, save customer. So when I call the save customer method in my test, the add record method gets called on the mock repo, which raises the event which is handled here in the failed database request event handler. So again, I'm testing the behavior of the system under test, not just to pure ins and outs. So any questions so far? No. Okay. Let me go through a couple bonus features. A little error. So we can do a call back. And we can say before the mock executes do something after the mock executes do something. I very seldom use these. But they are good for like if you're if your system under test is just not behaving the way it should. And you want to add some additional logging or as we talked about before with the, you know, alert made it here alert made it here as we used to classic ASP, you get that power to do some additional logging in there. I don't use those much in real life. But what I do use is the difference between loose mocks and strict mocks. A loose mock is what we've been using so far. Anything that's called on a mock, that is a quote unquote loose mock that doesn't have a set up, we'll just return a default. So the example where I said, call find method with 12 return the customer. But my test actually called find method with 13 and return no. That's a default behavior for a mocked object. But if we want to be strict about it and be hardcore, then we can set up the mock as a strict mock. And then anything that's called on that mock that doesn't have a setup will automatically throw an exception. Now why would this matter? Well, I am expecting the find method to be called on my mock. But there's also the add method, the, you know, log database error method, right, all these other methods on there. If I make it a strict mock, and I only set up to find method, and the update method gets called, yeah, it throws an exception. This is this will be a side effect bug, right, because I'm calling something else that I don't want to be calling. And I can trap it that way. It doesn't look like I'm making sense to you. I think he just lost me. Okay. I have a strict mock right here. Yes. I have a controller that takes the strict mock of the I repo object. I set up the expectation that I'm going to call get customer with an ID, I'm sorry, I'm going to call find, yeah, with the parameter of 12, right? I haven't actually set it up, right? There's no mock dot setup, learn how to type mock repo dot setup, right, I would have to put in my expectation in here x dot find 12 dot returns new customer. But what if that number and that number don't match, and I'm actually calling in my controller a different number, right, definitely behavior I don't want to have happen. Okay. So I go back into here and I have I call find with 12 returns a new customer. And then I want the mock to fail in a glorious manner. If anything is called on the mock that I haven't set up. Okay. I have not set up find to take the parameter of 13. I've set to find method to take the parameter of 12. So when I run this test, let's debug it. But it's, it's a mock. Why do you, why do you care? You're, aren't you already deciding what it returns because you're not actually testing the call to the actual testing the thing that's using the mock? I'm not testing the mock itself. I'm testing it right using the mock. Okay. So I have a strict mock, right? So there's my controller passing in the mock. I have my ID of 12. I'm setting up that when you call find with 12, it returns a new customer. So remember, we are expecting our system under test to take this parameter and pass it into the find method. But we have a bug passing in a different parameter. Well, if I said it dot is any, and it will take any integer, then this test would pass. Okay. But we want to make sure that it doesn't pass because of the fact that we didn't set up the behavior to work with 13, we set the behavior up to work with 12. Okay. Got it. Right. Another way to look at it is what if in here, I had a bug where I said repo dots add record, right, I'm calling add record in the get customer. And I go back to my behavior and let's, let me just go back to the controller. Sorry, let's fix this bug. So we fix this bug. It's no longer a problem. But let me put a break point right here. Go back into the tests and debug it. So we create a mock of the I repo. We set it up to call find with a 12. But it's strict. So if it just recalls find with a 12, we're golden. Okay. To behave as expected. But what happens is we have a debugging issue. We're calling add record, add record was never set up. There's no expectation around it calling add record. If this was a loose mock, which is the default behavior that would say, I don't care. Okay, I'm not going to do anything. But you called me, right, and we're going to ignore that. But because it's a strict mock, immediately upon that unset up call throws an exception. Okay, you called a method you weren't supposed to naughty boy. Right. And again, that's more for testing the behavior of your system under test than the actual results of the inputs and outputs. Right. Does that make sense now? Yep. Yep. Last thing I want to cover. And this implementation has gotten better over time, but it is a performance hog is mocking concrete classes. Everything we've shown so far is talking about mocking and interface. Right. And that's basically free because all we're doing is creating essentially a new instance of I repo happens to be a proxy and there's some magic going on behind the scenes. So we can do the setups and the verifications. But we can also mock concrete classes within limits. Now there are some commercial products out there that you can buy that will mock statics and internals and protected and everything else. But we're talking about the free tools here. So there are a few things you can do. I have a concrete implementation that I want to mock. And what I am mocking here is a fake repo. So you talked about fakes. So now I have a concrete class that implements I repo and is hard coded to behave a certain way. Right. Well, the problem with hard coding to behave a certain way is then I can't change the behavior to test a different case scenario. I have to create a new fake with MOQ or mock you. You can actually do a little bit of mocking of concrete classes. So on my mock repo, I let me skip that test. Sorry. That one I wrote late at night and I'm just blanking on what I'm trying to test. Let's look at this one. Okay. Where I have a fake repo and I'm mocking it. And what I'm doing is I'm setting up that a protected member and I would do the same thing with any virtual member. But the get number returns a 12. The get number with parameter which takes any int returns a 15. The difference between mocking a protected and mocking a regular is just the fact that we have to call mock dot protected. But there's something very important I have to point out in that anything that you want to expose through a mock on a concrete class has to be marked virtual. Think about what a mock is doing is creating a proxy around that thing that we're mocking. Very simple with an interface a little more complex for the concrete class unless those items are marked virtual right because then what it's not doing is it's not creating a proxy it's actually deriving from that concrete class and the proxy is going around that derivation. So we just have to make sure that we mark our methods virtual that we want to be more okay to be mocked. And then the last thing I'm showing off here and this is I think it's cool. I've never used it in real life because I do things a little differently. But that was pretty cool. I have these protected classes in this first example starting with line 37 we've got magic strings right I have to do the mock dot protected set up returns an int with the name of the method. I'm not a big fan of magic strings because I refactor my method now I've broken this code right. We can actually set up a mock interface as long as it has the same signature as our protected methods then we can say mock the fake repo using protected methods as if it was this fake mock interface then we can use this lambdas to with get number and get number with param now this does not completely protect us from breaking because if I go into my fake repo and change from get number to get number two for example that can break. So what we want to make sure that we do on this fake repo is pass NF because of my inheritance scheme I can't do it is I can just need the power clipboard inheritance right. So we want to then make sure that we put that interface on our class and the problem is now we have protected issues with interface methods that are not much protected what I'm trying to demonstrate here really is don't mock concrete implementations it gets hairy okay right but sometimes you've inherited code you've got this legacy code out there there's no interfaces I have all these dependency things I want to refactor two interfaces but as we'll talk in the episode on working with legacy code you can't just dive in and start changing code without some sort of safety blanket right so at some point in time you probably have to mock a concrete class I would suggest that be a stop gap and as you convert those things to interfaces you actually delete the test of mock the concrete classes and replace them with tests that mock the interfaces okay but you've got the power to do as a bridge technique until you get there again the commercial versions that you can buy of mocking tools are much more powerful I would argue if you're writing code the right way following solid then you probably don't need the commercial versions okay and that's really my my whirlwind tour of mock you all right a lot of information in a little compact that was kind of deep I think that people should start playing around with it learn this in kind of bite-sized chunks that was quite a bit of drinking from the fire hose right but a lot of power in there and as we saw it works great with x-unit and really gives you the ability to kind of stub out the implementation of doing things that are expensive time consuming so just talking to databases and services yeah and we'll we'll write this I know we just showed you a lot of features boom boom boom boom boom and sometimes it's like whoa how do you apply that we're going to apply all these tools in our next show excellent okay right so but I wanted to make sure everybody understood what we were doing so we could not have to spend time saying well what is a mock right and what are you doing and what is the setup and what does verify mean so we can actually just say hey let's write some tests around some legacy code and we want to stub out some things and we want to mock some things right and go through that cool all right and we will do that in the next show so see you next time on visual studio toolbox thanks for watching