Making unit tests simple again with .Net Core and EF Core | Jernej Kavka (JK) at DDD Sydney 2018

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
thank you first I would like to thank the partners to make this even happened and also thank you guys for making my presentation happen as well it's my first DDD talk and let's get started so my presentation is about making unit has simple again with dotnet core and EF core my main focus is going to be the EF core part and a little bit more pragmatic approach to unit testing so first I am in Akaka but you can just call me jackée and I'm Software Architect at SSW you can follow me on Twitter on github or on my blog JK - dot me and lately I'm focusing mostly on dotnet CO and cognitive services so why would you do the effort doing the unit tests so you heard from a lot of people they're saying like it's not worth the effort it's takes too much time or you know they just don't feel like they have the skills to do the tests so for once unit hands can self is a live documentation and then it helps to prevent you over-engineer stuff because you have a clear goal what you supposed to test and you don't try to do much more than what's needed for the test in the future it gets simpler to add features and refactor with confidence especially on big projects where any change can break your code helps prevent bugs especially the regression and the jury is out that it does actually speed up development but it takes a little bit time to learn properly use unit us but once you go over that hurdle it does speed up the development so what I'm going to show you is a bit more pragmatic approach and the key takeaway will be that you should start doing unit tests should be afraid doing unit tests and the quote here sums it up perfectly and imperfect tests run frequently a much better than that perfect as that are never written at all you can wonder why you can guess why that is but this is now the basics of the unit tests I'm going to cover and we're going to move to more technical part which is the EF core so how many of you have used unit tests in the past not quite a lot and how many of you have used EF core so not many so what EF core is it's a lightweight extensible and cross-platform or M so you can basically access the data base wide in an abstract way EF core has several providers that allows you to connect a sequel server or call sequel light or many more and the very important part of the EF core is that the dbcontext the part that allows you to connected us provide us is not testable in EF core so the d DB context now works as a unit of work and the DB set inside of DB context works as a repository and if you were in the previous session Jason was talking about a lot of points about that you may not need to use repositories and unit of work in EF core anymore and we have that recording and I encourage you to check that one out if you want to know more about data Sophy of course specifically but what we're going to focus is to provide us and they both used specifically for unit testing one is in-memory non-relational provider and the other one is the sequel light relational provider and they both use to be able to simplify unit testing because in a lot of cases our code depends on doing operation on the database and sometimes abstracting that layer is very difficult but it you shouldn't be using it to try to mimic the database you shouldn't be checking for foreign keys and things like that this is specifically used for making unit testing simpler so for the first demo on that I'm going to show you I'll first show you the setup I have made and then I'll show you the live demo so what we have set up here is the bare minimum for a persistence layer so we have a simple class library which contains a person data structure with first name last name and an ID and a DB context so here is the context it has the pay minimum configuration for a DB context and we have a people's table and here we have the actual structure of the project and as you can see here we have only one dependency and that's my Microsoft entity framework or 2.1 so the next snap is how do we create unit tests so when you create a new unit test in a file new project you'll have different templates like for X unit and you need ms test you just create a new project and all you need to add to be a to do EF core testing is the entity framework test adapters in this case in memory and sequel light adapters the next phase is the actual test so I'll go through this code so first we have the Builder this building is basically how we construct the dbcontext it's something that you may even use on the production code via dependency injection but here we explicitly creating the the options build up then we take withheld that builder to say hey we're using in-memory database and we're using a random name because we want to ensure that the database is always unique always empty and after that we create a context of sample DB context and we put those options in and the last part is just that simple task we wanted to test in the first place and in this case we're just testing whether we can add a person save it to database and then retrieve it back so that's the in-memory provider if we have a look at the sick light provider the major difference is we tell the options build that it should use SICU light provider red and then in-memory provider and we say that the data source is memory we don't have to generate a unique names for sequel ID and what's important is we need to open connection and ensure created and if we compare them side-by-side you can see that from the test perspective it's everything the same it's just the setup of the context to see that it's different so now if we move to the first demo I'd like to show you something so we can traditionally just select and run all our tests we went for the project build we went for a test run and then we see the results what what I'll show you is a better approach that will hopefully help a lot of you to speed up development I think this is the single best feature in Visual Studio 2017 for unit tests what it allows you is to see not just the result of the unit test on the left side but what I can do here is change and I haven't saved yet and it will tell me hey this unit tests failed so I can code and while I wait for the result I can already think about the next step and if you didn't believe me that we need your open connection I can just comb it out and you'll see that the test actually is going to fail so you can have you can really quickly iterate your code and see what's working what's not working and really focus on the actual problem rather than running and debugging can you repeat the question so it uses the same test adapter than this than the one in test Explorer so the question was how it doesn't know whether it's fail or not it's because it uses the same test adapter than the test Explorer there's nothing so answer this question yeah it runs in the background yeah so okay that's all for the first demo so the second demo will be slightly harder but just slightly and we're going to use Jason Taylor's Northwind project the same one as in the previous session how many of you were in the previous session now that's great so we don't need a long introduction and what we're going to do is something very simple we're going to update change employee manager command and we're going to do an integration test for a report query so let's switch to the Northwind traders here I have just for those who are new I'll just quickly show you it's really slow so what we're going to focus here is mostly the application layer and application test layer but we also have already prepared persistence and presentation layer but I use this project so we can just type directly into data and how to use this in a real application and before we start with the test itself I have prepared a test base which is inherited by all tests and the main purpose for it is to generate the dbcontext and the differences you have seen between the in-memory provider and the sequel Lite provider is handled here so if we use the sequel provider we ensure the connection otherwise we just make sure that the database is created and we switch through use sequel Lite if we interested in this code at the end of the presentation I can provide it the URL and the last part before we start with the actual test is the init and gat what it does is it creates the DB context it sits employees and returns the context so we have a little bit of data to play around without test and if we look at the first test what we're trying to do is we're trying to assign a manager to an employee and then we're trying to assert whether that change was successful and what I can do now is I can use the life unit testing and I can start and exclude all but this nest so you can really focus your testing just this test on the bottom here we can see the progress and we can see that the task has failed and if we go into the method you can see that it has missing implementation and if we just copied this around and paste it here and just imagine that we are actually doing coding right now when I do this I don't have to go back to the code to see oh this nest and now it works I can just do the code inside the command or query or any way where the witch is being run by the test and I can see the results as I type yes so remind me that at the end and I can show a show a demo of that but yes you see a red crosses for the field test and green I'll show it at the end just remind me so that covers the very basic scenarios but what happens is okay the test this comes deep and say hey you know that you cannot be manager to yourself I was like okay and then I've written and also you you have forgotten I case a test case where a non-existing person cannot be a manager or you cannot assign it to a non-existent person so written in new test which what it does is it's the same one as before but we're trying to add in non-existing manager when we try to run this test we'll find something very interesting it will fail but here we will going to see a where different providers come into play because the reason why this is failing is not because the actual command failed but because the field didn't feel at all so for instance if I copied this part run it over here and let's comment this out it will be perfectly happy but we don't have a manager of ID 3 it doesn't exist and this is one of the things you need to keep in mind when you're using in-memory database if we use for instance sequel ID provider this distance is going to fail so if we look at here it feels correctly because there is no foreign key and this is where you can see one I like to use the different providers in memory Pravana I use because it's fast it's equal light because I can enforce those things but as a proper unit test you should never rely on the actual database so you shouldn't be relying the database telling you there's no foreign key so instead of fixing that part with help of database we're going to go into the command and I already prepared the next part and we're going to pace this part here and we have yet again another passing test and this is very important to know that you should always test how the application behaves not database so ideally if when I remove the sequel light it provided it should work the same in in-memory but sometimes you have complex updates and you actually need to verify whether there's any foreign key conflicts and the last one is very easy you cannot be manager to yourself now here we feel not big because of the database even if you use a Seco light will have exactly the same result here we failed because this is a business requirement so if we copied that and one thing to note is if you look at this line over here you can see there's a blue - the main reason why I added this case is that blue - means that the code hasn't reached there yet so you can actually see how far the the code has gone based on what you see on the left because if I throw an exception over here you'll see that the code executes all the way to the exception and everything is blue so if sometimes you're asking yourself Oh where does it break with that point where we get a an exception it can quickly iterate through with the life unit test instead of spending a lot of time on debugging the application in going line by line so once I uncommon this part we have all test green and to verify that I can just make sure that when I do the life unit testing I go to the class level and now when I'm on class level I can exclude everything but entire class so now I'm doing a unit testing on the entire class I switch back to the command and I can see that all lines are green so and for answering your question before if for instance I'm a quant has a field that feels only on one specific line if we switch back you can see that everything is rat this line is blue which should have been covered but because I broke the test isn't covered but the one that is always successful in all tests is green so you can have a quick look at which parts are actually breaking in which parts their parts are good let's put back to that and last two demos is what sometimes happens is you need to do you need to run sequel statements it might be because of the performance reasons it might be the sequel is provided to you and you just have to use it and you don't have to worry about that because you've core with help of a sequel light covers that so if you run this test it's going to be successful and if we look what's going on we are actually executing a sequel statement and we're using the new query async from AF core 2-1 to be able to directly translate a sequel result into a model and what it gives us an additional benefit is we can use where clause order by and other link statements on top of that query see you no longer have to do specific select statements or get all the results from the database and then do the crash in memory and just to prove the point if I've removed the sequel light provider this is going to fail because in-memory provider does not support relational database and something very interesting happened with EF core to one as well is it now supports beers in to oh when you try to create a view with sequel Lite there were some weird errors and you couldn't really use it but with two one to my surprise it just works the only caveat is that usually those views are created outside of your DB context so you have usually we'll have to create them manually before starting the unit s of instance Here I am actually creating the I'm executing the creation of the view before I start the query because net view only exists in the production databases but otherwise this is exactly the same test and again it works only on sequel Lite provider so I hope with that I give you a little bit of glimpse how you can use the EF cope up providers to more easily test your unit test and hopefully also showed you that writing tasks isn't really that hard and those nuts for some would be like yet the integration test they are not strictly correct and you should think the pragmatic approach you can always mock certain miles less a little bit later you can refactor your code make it as better but if you can write a test that the tests the right thing that captures the Brightbox you should do them now and make them better over time and just the finish of the EF core part you have seen that I was using in memory and sequel I'd providers and when would you want to choose which one I would say always use in memory provider unless you there's a reason not to specifically because of speed and the other one is the consistency of order so when you do a select statement in in memory you'll get one order in cycle light you may get random orders each time you call but in memory provider is in relational debase so forget about foreign key constraints and other features but it will EF go is smart enough to be able to do join tables and similar features and it doesn't support a sequel statements now seek alight as you have seen does support foreign key constraints and it can run sequel light statements but it can take up to five times longer to execute the statements and as a set inconsistent orders and although it's a relational database keep in mind this is not a sequel server it does not have all the features and we need executing row sequel statements they might not be the same as the sequel server so the key takeaway from this presentation would be keep it simple the last dependency you have to the tests the better so I did forgot to show you and I do have a little bit time to just show you what I mean with that with that so we have here a test you should not be a manager to yourself what if I tell you that I can do this I can just not use a context at all and when I run the life unit test it will run very happily and if I completely remove this spot it will run completely happy and you should do that simply because the last dependency you have the less chance that has fails because of something that is not relevant to this test make it snappy basically you don't want slow unit tests because you want to run them as many times as possible as frequently as possible and if you have a global seed that means that the time for the application to execute for the test execute can increase and if there are too many tests depending on that one seed you have an exponential growth in test execution and focus on what's important for the test what happens sometimes is we try to oven engineer things or we try to test things that are not really important for their business and sometimes we just need to pick the battles and focus on things that are important so with that thank you and if there are any questions or if you're more interested in more details between differences of ef4 c.coli provider or in-memory provider or you're more interested about unit testing in general I have a few more demos I can go through I think it's dotnet core the EF core 2.2 for Cosma support the question is for EF migrations they mean migrations in generals database migrations yes they are supported I can actually show you in this project we do have migrations over here let's zoom in a little bit so it the my EF migrations are very similar as before they just don't use binary files anymore when they do divs they use tax snapshots which is much better yeah and they just work as before but in two one they did did add data seed migrations which is new to EF core so you can specify a specific seeds for the table any other questions yes I haven't done specific performance task but with EF could to one the need for dapper has drastically reduced specifically because the query acing but I haven't done performance tests so in short I used to depend on data into or to offer sequel light when it comes to gooood conversion type and some sequel execution but now I'm just using a EF core any other questions sorry can you beat radish if we use reactive extensions no but I think Brendan did something regarding perfect you can just go to his talk so for stop procedures based on my understanding they are not directly supported the last time I checked but you can execute the sequel statements that execute slope rocks and then do the mappings we have another question over there can you repeat the question please so the question is if we can exclude certain classes from the unit test so when you're using the in memory and sequel I provide us the migration is not being run so it just takes the current domain whatever you set up and just takes that it doesn't look into dem aggression so even if you put for instance a view into migration step it won't be available to the test so the question the real question is when you have a coverage code coverage tool whether you can exclude for instant migrations from that coverage yeah I believe that's that's very specific to the tool you're using and there are many tools here out there for code coverage so yeah you'll probably have to look for that specifically yeah for this yeah specifically there is I don't have the internet right here but when you have I believe its category or test category or something like that then I remember exactly how it's called categories in X unit you can actually specify a specific category that got it gets removed from the life unit testing and by extension the code coverage by life unit testing and I believe there's another one that also is all for excluding to the code coverage in general or at least the Microsoft code coverage I believe it's right yeah you can set up the trait but I don't remember at precisely what what's the name of that that category category can act agree yeah yeah so if you interested I can show you a little bit wider or want to use sequel light all the time just to prove your point just quickly do this was really fun when I discovered I'll be running two tests side by side and they both are for performance test one is in memory and where are you performance yeah so this this project is specifically designed to give you a little bit more side-by-side comparison and it's nicely this described in my blog post well this is executing you can quickly show you you can actually have a YouTube unfortunately doesn't work here but you can have a look into the YouTube I am actually going through each difference between in memory and if Co provide this and if you move interests that you can just look into this YouTube it's a little bit more in-depth it is currently for EF core 2 also it not it's not quite up to date but I think if you're very interested into that definitely I have a look into that also you have the all the samples here and you also have the updated URL down below for the actual source code for this specific presentation and I'll be making another blog post specifically for this content so if you go back you can see that in memory provider takes seven seconds and sequel I took 19 seconds so we're not I think if there are no other questions thank you for listening and [Applause] [Music]
Info
Channel: SSW TV | Videos for developers, by developers
Views: 15,743
Rating: 4.9144387 out of 5
Keywords: ssw, software, .net, .net core, dot net core, ef core, efcore, .netcore, jernej kavka, ddd, ddd sydney, ddd sydney 2018, unit test, unit testing, SQLite
Id: 6nYefHkKby8
Channel Id: undefined
Length: 39min 8sec (2348 seconds)
Published: Thu Oct 18 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.