Business Logic Testing Templates and Tips

I have two levels of verification in my application. First, object authentication is performed using the bean verification API (for example, required fields). The second level is a test of business logic. For example, the user has a message. A user can delete a message only if he is the creator of this message and has posted a rating of <50. Therefore, I need to do something like this:

if (post.getCreator().equals(session.getUser())) { if (post.getRating() < 50) { postRepository.delete(post); } else errors.add(400, "Cant delete post with rating 50 or higher") } else errors add (400, "You should be owner of the post") 

I do not like this method because these conditional expressions are reused and I have to duplicate the code. Moreover, if the number of conditional numbers is more than 5 or so, it becomes unrealistic to read and understand the code.

In addition, the standard Spring validator will not be very useful, since I have to create another check for one object for different actions (for example, delete and update)

So, I'm looking for a way to make this smarter (the template might be), and I would be very grateful if someone could give me a hint.

Thanks in advance!

+7
java spring design-patterns validation
source share
2 answers

You can use the strategy template .

Each condition can be modeled as a function that receives a message and session and can return an error:

 Post -> PostContext -> Optional<String> 

You can represent this using the interface:

 @FunctionalInterface public interface ValidationCondition { Optional<String> validate(final Post post, final Session session); } 

So for example:

 public class CreatorValidation implements ValidationCondition { public Optional<String> validate(final Post post, final Session session) { if (post.getCreator().equals(session.getUser()) { return Optional.empty(); } return Optional.of("You should be owner of the post"); } } 

Then you can save each check in a list:

 final List<ValidationCondition> conditions = new ArrayList<>(); conditions.add(new CreatorValidation()); conditions.add(new ScoreValidation()); // etc. 

Using the list, validations can be applied in bulk:

 final List<String> errors = new ArrayList<>(); for (final ValidationCondition condition : conditions) { final Optional<String> error = condition.validate(post, session); if (error.isPresent()) { errors.add(error.get()); } } 

Using Java 8 lambdas, you can declare them inline:

 final ValidationCondition condition = (post, session) -> { // Custom logic }); 
+6
source share

Strategy is a decision, in my opinion. I will give you a very simple example. Let's say we have two types of credit cards: Visa and Mastercard. The logic for performing a payment operation is the same for both cards, but checking the card number is different. Thus, passing the VisaStrategy object through the workflow, performs the same logic and operations as we do, passing MastercardStrategy, except for one - confirmation of the number of cards that is executed within each specific Strategy class, so you don’t have any "if still "your code in general. Each strategy class is now responsible for one and only one type of map check. If you are looking for a flexible and easy-to-maintain code structure, use the strategy strategy template.

+2
source share

All Articles