How to test domain validation in unit test cases
Posted By : Shiv Kumar | 19-Jun-2015
Get started with unit test case, the first thing to test is domain - the very basic and important building block for entire development process.
During domain unit testing, the main focus is on constraints validation.
Domain classes are tested by using DomainClassUnitTestMixin or the HibernateTestMixin.
Domain to test :
class User { String username String password static constraints = { username (nullable: false,blank: false, unique: true, email: true, maxSize:60) description (blank: false, minSize: 10, maxSize:600) } }
Here I am discussing two ways of domain constraints validation testing by using GrailsUnitTestMixin:
Way 1 : By using mockForConstraintsTests
GrailsUnitTestMixin provides a method called mockForConstraintsTests used to mock validation support for classes.
mockForConstraintsTests makes the testing task easy by changing the behavior of the errors object and domainClass.errors[field] gives us the name of failed constraint.
If we dont use mockForConstraintsTests, the validation errors are of type org.springframework.validation.FieldError object like :
Property [{0}] of class [{1}] with value [{2}] must be unique Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}]
Test case :
class UserSpec extends Specification { def setup {} def cleanup() {} @Unroll def "test validation on username for the error : #type"(){ given : mockForConstraintsTests User User user = new User(username : '[email protected]',description: 'test description').save(flush :true) when : User testUser = new User(username : value) if(type == 'unique') mockForConstraintsTests(User, [testUser, user]) // check for the uniqueness between two user objects then : !testUser.validate() testUser.hasErrors() testUser.errors['username'] == type //mockForConstraintsTests gives the name of failed constraint where: type|value 'maxSize'|'L'*61+'@gmail.com' 'email'|'abc' null|'[email protected]' 'unique'|"[email protected]" } }
Way 2: By defining custom abstract class and extend it instead of Specification.
Create your own abstract class like :
import spock.lang.Specification abstract class ConstraintUnitSpec extends Specification { String getLongString(Integer length) { 'b' * length } String getEmail(Boolean valid) { valid ? "[email protected]" : "testemail@g" } String getUrl(Boolean valid) { valid ? "http://www.google.com" : "http:/ww.google.com" } String getCreditCard(Boolean valid) { valid ? "4111111111111111" : "41014" } void validateConstraints(obj, field, error) { def validated = obj.validate() if (error && error != 'valid') { assert !validated assert obj.errors[field] assert error == obj.errors[field]?.code } else { assert !obj.errors[field] } } }
Now you have to modify the above test case little bit like:
class UserSpec extends ConstraintUnitSpec { // UserSpec extends ConstraintUnitSpec instead of Specification as done earlier def setup {} def cleanup() {} @Unroll def "test validation on #field for the error : #error"(){ given : User user = new User(username : '[email protected]',password: 'Admin@1234').save(flush :true) when : User testUser = new User() user."${field}" = value then : validateConstraints(testUser, field, error) where: error| value | field 'nullable'| null | 'username' 'blank'| '' | 'username' 'maxSize.exceeded' | getLongString(61)+'@gmail.com' | 'username' 'email'| getEmail(false) | 'username' 'valid' | getEmail(true) | 'username' 'nullable' | null | 'description' 'blank' | '' | 'description' 'minSize.notmet' | getLongString(8) | 'description' 'maxSize.exceeded' | getLongString(601) | 'description' } }
The main concept of abstract class is to make the things reusable through out all the test cases and define custom getter for email and other things which maintain the code neat and clean.
Enjoy the stuff.
Thanks
Shiv Kumar
Cookies are important to the proper functioning of a site. To improve your experience, we use cookies to remember log-in details and provide secure log-in, collect statistics to optimize site functionality, and deliver content tailored to your interests. Click Agree and Proceed to accept cookies and go directly to the site or click on View Cookie Settings to see detailed descriptions of the types of cookies and choose whether to accept certain cookies while on the site.
About Author
Shiv Kumar
Shiv is an experienced Java Developer with a strong background in multiple technologies. He specializes in defining system architectures to ensure reliable and resilient solutions. He possesses a comprehensive understanding of the latest technologies and has hands-on experience in Core Java, Spring Boot, Hibernate, Apache Kafka messaging queue, Redis, as well as relational databases like MySQL and PostgreSQL, and non-relational databases like MongoDB. He excels in API implementations, Microservices, Web Services development, testing, and deployments. Shiv actively contributes to code enhancements and consistently delivers valuable contributions to various client projects, including Fabtrack, Pando, Pandojo, Digikam, WhatsApp Integration, Croniz, Punchin Application, Script TV, Bhaasha, and more. He demonstrates strong analytical skills and a creative mindset. In addition, he has a passion for reading books and exploring new technologies and innovations.