blog.smart-java.nl
Ordina J-Technologies – Java Blog



Unit Testing a Bean Validation ConstraintValidator

By: Jan-Kees van Andel, 12 March 2010

I’ve been playing a bit with Bean Validation and thought I found an issue: Unit testing a ConstraintValidator. Specifically, parametrized ConstraintValidators.

First, what’s a parametrized ConstraintValidator? Simple, a Validator that takes a parameter to do its job. A simple example is a length validator that takes the minimum and maximum length as parameters and validates if the value is between those two.

Parametrized ConstraintValidators are everywhere, even Bean Validation itself contains them. For example: @Min(length) and @Max(length), but also normal ConstraintValidators, like @NotNull where you can customize the error message. However, this error message parameter is not very interesting with regards to unit testing individual ConstraintValidators, because the message is generated by the Bean Validation framework.

For example, consider this ConstraintValidator, incl. corresponding annotation:

In the future, Bean Validation may become the core mechanism for ensuring correctness in your system. For example, JPA 2.0 leverages Bean Validation annotations to generate additional DDL statements and JSF 2.0 automatically uses Bean Validation when it’s available. Note: JSF 2.0 uses a new concept, called “default validators” to implement this. A default validator is invoked on every input component on a postback.

But, how do we test this stuff? After all, you can’t instantiate an annotation.

I currently have 4 options:

Using a declared annotation
The first attempt is shown below. Here, I simply declare the annotation in my test case on a dummy instance field (an annotation doesn’t live on its own) and look it up using reflection. This way, Java takes care of instantiating and initializing the annotation.

I personally quite like this approach. The test data is inside the test case. Unfortunately not in the test method, that would be better, but since you can’t put annotations everywhere in your code, it’s not easy to implement this decently.

So let’s look at the next one…

Custom annotation implementation
Since Java annotations are just a special case of interfaces, they should be fairly straightforward to implement. However, for some reason, I didn’t know this until recently. But it’s actually not different from any other interface implementation. See for yourself.

Nothing special, right? But I don’t really like it. I could have also written it inline, but I don’t like that either:

I think the above one looks like garbage. So this is also a no-go.

Dynamic proxies
Java itself uses dynamic proxies at runtime to instantiate annotations. So why not also use a Proxy to mock the annotation? See for yourself.

However inline, the implementation looks very clumsy. Unfortunately this is probably as simple as it can get, since you DO need to define the inner class.

And it will become even worse when there are multiple parameters on the bean, since you need to check which method is invoked. This will make the implementation even worse.

Mocking using Mockito
But, creating and configuring proxies, isn’t this what mocking libraries do? Exactly, let’s try.

This looks pretty nice. And it scales well with multiple attributes.

I only doubt it will be the nicest solution when the annotations become more complex. I really don’t like annotations that contain annotation parameters. Or even worse, arrays of annotation parameters. But reality is, they exist. And if they exist, they also need to be tested. But, OTOH, people who nest annotations probably don’t mind unreadable unit tests. ;)

Laat een reactie achter