Yes, you must fully test the database. The time you taunt is less, and the value you get from ridicule is much less (80% of the likely errors in your system cannot be discarded due to ridicule).
When you check all the way from the controller to the database or web service, this is not called unit testing, but integration testing. I personally believe in integration testing, not unit testing. And I can successfully complete the test development.
Here's how it works for our team. Each test class at the beginning restores the database and fills / sorts tables with a minimal set of data (for example, user roles). Based on the needs of the controllers, we fill out the database and check whether the controller performs its task. This is designed in such a way that damaged DB data left by other methods never ends. With the exception of the time that needs to be done, almost all the qualities of a unit test (although this is theory) are gettable.
In my career, there were only 2% of situations (or very rarely) when I was forced to use mocks / stubs, since it was impossible to create a more realistic data source. But in all other situations, integration tests were possible.
It took us a while to reach a mature level with this approach. we have a good structure that concerns the aggregate and search for test data (first-class citizens). And it pays off a lot of time :). The first step is to say goodbye to bullying and unit tests. If ridicule does not make sense, then they are not for you! Integration test gives you a good sleep
=====================================
Edited after the comment below: Demo
An integration test or a functional test must deal with the database directly. No ridicule. So these are the steps. You want to test getEmployee () . All these 5 steps below are performed by one test method.
- Drop db
- Creating a database and filling in roles and other information data
- Create employee record with ID
- Use this identifier and call getEmployee ()
Now Assert () / Check the returned data
This proves that getEmployee () works. Steps to 3 require that the code be used only by the test project. Step 4 calls up the application code. What I had in mind is the creation of an employee (step 2), should be performed by the code of the project code, and not by the application code. If application code exists to create the employee (for example: CreateEmployee () ), this should not be used. Similarly, when we test CreateEmployee () , then GetEmployee () should not use the application code. We need to have a test project code to retrieve data from the table.
So no bullying! The reason for the failure and creation of the database is the prevention of erroneous database data. With our approach, the test will pass no matter how many times we run it.
Special tip: in step 5, if getEmployee () returns an employee object. If the developer later deletes or changes the field name, the test is interrupted because the fields are checked. What if the developer adds a new field later? And he / she forgets to add a test for him (to approve)? The solution is to always add a check on the number of fields. for example: The Employee object has 4 fields (First Name, Last Name, Designation, Gender). Thus, the number of fields of the employee’s object is 4. And our test will fail due to the calculation and will remind the developer to add a confirmation field for the newly added field. And also our test code will add this new field to the database and receive it and verify it.
And this is a great article that discusses the benefits of unit testing integration testing.