Given, when, assertions and confidence in implementation

In the last text about assertions , something important was missing and was not agreed.



What is the difference between given and when and how is this related to assertions?



The idea underlying this is simple - we want to limit the number of assertions.



Consider a small example.



Let us pass some valid object to the method, call the additional service and enrich its properties.



I should not write the code ahead of the test, so we will assume this is only for conveying the big picture.



public User enrichUser(User validUser){ user.setDetails(enrichmentService.getUserDetails(validUser.getId())); return user; }
      
      







We are not interested in validUser variations. It is not null, it always has an id, then it is valid. This is precondition, i.e. given.



In fact, we need to consider two conditions - enrichmentService fail and success. This is a condition, i.e. when.



How to distinguish one from the other? Given does not require verification of other cases, when - requires. Those. whenValidUser requires whenInvalidUser, and givenValidUser does not.



And enrichmentservice == null? If we injected a dependency, then we can consider this part of the configuration and not think about it in the tests. Absolutely. There are preconditions that it makes no sense to list.



If the method accepts just user, the number of scripts to check increases. Given becomes when.



Another question - but, strictly speaking, by accident or intentionally, a method can ruin a user for us? Shouldn't we check it out?



If we answer - yes, we must, we will have to admit that this can be a big burden. A user can have fifty properties, and checking them in each method can be expensive. There are bulk checks using libraries, but by doing so we lose an important function of the test - to prescribe the desired functionality, and not pick up the dirt behind the implementation curve.



This can be compared with the airport security - someone checks the ticket, someone luggage, someone pockets, and checks are not duplicated at every step. Those. Assets trust what the implementation will do and check only what they prescribe.



Thus, a properly constructed precondition reduces the number of scripts and assertions. We make assertions only on condition.



Unfortunately, frameworks like Cucumber do not make much difference, because preconditions themselves do not check for them that Given, that When is the same, purely descriptive term.



In more complex cases, it can be difficult to distinguish one from the other, which in itself smells. For example, many tests in a row check the same thing, or some of the conditions in the tests are forgotten, or ignored as inappropriate.



This is a good reason to restructure specifications and redesign.



All Articles