views:

79

answers:

5

Is there a less bloated way to test constraints? It seems to me that this is too much code to test constraints.

class BlogPostTests extends GrailsUnitTestCase {

    protected void setUp() {
        super.setUp()
        mockDomain BlogPost
    }

    void testConstraints() {
        BlogPost blogPost = new BlogPost(title: "", text: "")
        assertFalse blogPost.validate()
        assertEquals 2, blogPost.errors.getErrorCount()
        assertEquals "blank", blogPost.errors.getFieldError("title").getCode()
        assertEquals "blank", blogPost.errors.getFieldError("text").getCode()

        blogPost = new BlogPost(title: "title", text: ObjectMother.bigText(2001))
        assertFalse blogPost.validate()
        assertEquals 1, blogPost.errors.getErrorCount()
        assertEquals "maxSize.exceeded", blogPost.errors.getFieldError("text").getCode()
    }
}
+2  A: 

I'd advise against testing getErrorCount(), as you'll make your tests fragile (as you add other constraints, you'll have to remember to update every instance of new BlogPost() anywhere in your test cases). Just check hasErrors().

Other than that... for each constraint, you need to generate some test data that violates it, call the validation routine, and assert on the errors. This is the code you need.

Refactor out some methods to remove the duplication. example:

private void assertConstraintWorks(clazz, fieldName, testData, expectedErrorCode) {
    def instance = clazz.newInstance((fieldName): testData)
    assertFalse instance.validate()
    assertTrue instance.hasErrors()
    assertEquals expectedErrorCode, instance.errors?.getFieldError(fieldName)?.code
}

void testConstraints() {
    assertConstraintWorks BlogPost, 'title', '', 'blank'
    assertConstraintWorks BlogPost, 'text', '', 'blank'
    assertConstraintWorks BlogPost, 'text', ObjectMother.bigText(2001), 'maxSize.exceeded'
}
John Stoneham
A: 

Ross Niemi, a coworker of mine, created the Domain Expectations plugin which uses a nice DSL for exercising and validating constraints on grails domain objects. We use it at my work place, and I've been very happy with it.

Ted Naleid
A: 

Maybe not the answer you want to hear, but: Do you really want to test the constraints defined in your domain model? In essence, what you are doing here is testing the validation framework of Grails rather than your own code. Don't get me wrong, tests are necessary (especially with dynamic languages like Groovy), but IMHO one shouldn't just blindly test everything that comes across. Maybe I'm just not too much of an hardcore TDD guy, but I just don't see the point here.

Daniel Rinser
A: 

This blog post has a good description of unit testing constraints. One thing I didn't see above is the use of mockForConstraintsTests() (which eliminates need for mockDomain())

And to comment on Daniel, yes I would test the constraints defined in my domain model to assert that I have correctly constrained the domain model. You make a typo in a constraint declaration and you won't find it until an integration or functional test (and in the meantime will drive you nuts)

zentuit
A: 

Does anybody know how I could get the fieldError to print out in the example below.

for each item, with an error I would like to print custom error messages that I have defined in the messages.properties file

at the moment all this does is print the default error codes

item.errors?.allErrors?.each{ println it.toString() };

thanks for your help

MTH