0

a discussion that rose among us devs: how to do unit test of Business logic layer that depends on data access layer. the two options are

  1. create test data in a test database (for example, H2). let the Business logic layer call the real data access layer that is injected with test database connection.

  2. mock the data access layer.

I can see pros and cons for the two options:
option one imitates production more closely. however, it compromises the isolation of the unit test. the test might fail because of a bug in the data access layer.
The 2nd option is vulnerable to the scenario where the logic inside the data access layer changes (with no changes to the api). in that case, the returned mocked value maybe obsolete.

would love to hear opinions on the matter (perhaps more options?)

  • 4
    Possible duplicate of [Do I need unit test if I already have integration test?](https://softwareengineering.stackexchange.com/questions/204786/do-i-need-unit-test-if-i-already-have-integration-test) Note your option 2 is "unit testing", your option 1 falls into the category "integration testing". – Doc Brown Nov 21 '19 at 12:38
  • "returned mocked value maybe obsolete" - your test should have full control over the returned value, otherwise, it's unpredictable. You are not testing the database, you are testing the code that works with those objects; your tests should be very specific. If the database returns something different, that requires different processing logic, then a *different* test should cover that. And if the core logic itself changes, then you simply have to rewrite the test(s) anyway. – Filip Milovanović Nov 21 '19 at 14:13
  • @FilipMilovanović, maybe I didn't explain clear enough: if the data access layer is mocked, then any changes to it are not reflected in the unit test of the business logic layer. if the logic inside the data access layer is changed, **I expect the unit test of the business logic layer to fail**, reminding me to adjust the business logic layer to the modified data access layer. this will not happen in a mocked data access layer. so basically I have to remember to change the unit test of the business logic layer in case of changes to the data access layer. – Sharon Ben Asher Nov 21 '19 at 14:19
  • 2
    The whole point of having layers is that changes behind the interfaces of one layer will not cause the code in another layer to fail. So *those* tests shouldn't fail; also mocks don't represent the internal logic in DAL, they represent the data returned by the DAL in a format specified by the interface between those two layers (or externally visible behavior). So they *shouldn't* reflect internal behavioral changes in DAL, only the changes that affect the layer boundary, and you shouldn't have to adjust the BLL (otherwise, you have coupling). 1/2 – Filip Milovanović Nov 21 '19 at 15:30
  • 1
    If there's logic in DAL that needs testing, a different set of tests exercising the logic in your DAL should fail, and possibly some integration tests. And if you change the interfaces, then, depending on how the thing is set up, either the tests (and the code) won't compile, or they will run and crash, or some integration test will fail. If none of that happens, then you should write better, more specific tests. 2/2 – Filip Milovanović Nov 21 '19 at 15:30

2 Answers2

3

Both options are valid and have advantages and disadvantages:

  • Option 2 is correct from "idiomatic" point of view because "unit" tests shouldn't depend on code outside of the unit (class, layer, etc).
  • Option 1 leads to creating "integration" tests and as you stated, that's closer to the production usage and verifies that the different layers work together correctly.

In the end of the day use whatever works for you, even both types of tests simultaneously.

Rumen Georgiev
  • 678
  • 4
  • 9
3

I think that it depends on which one is important for you.

I wrote unit tests in 2 different projects in a company where I had been working for a while.

Pros of mocking

  • The Unit Tests run fast according to saving really data to DB.
  • You do not have to maintain an extra database. Because if you are going to save data in reality, you have to create a test DB.
  • Sometimes DB connection problems might break your test even if your tests are not broken.

Pros of using real DB connection

  • You do not have to create an extra mock model each time.
  • Less complexity according to mocking.

Either way has its own pros and can be choosable rather than the other one.