Joseph
Joseph

Reputation: 1463

Grails Unique Id constraint in Unit test not failing

I'm upgrading from grails 1.3.6 to 2.2.4 and going through all of my unit tests. I have been replacing mockDomain with the @Mock annotation among other things. One of my tests is validating that IDs remain unique and fail if an id already exists. This no longer seems to be failing as expected. The test is as follows:

import grails.test.*
import grails.test.mixin.TestFor
import grails.test.mixin.Mock
@Mock(SecurityValue)
@TestFor(SecurityValue)
class SecurityValueTests{
    void testUniqueId() {
        def validEntry = new SecurityValue(id:"id",propertyName:"propertyName",userId:"testUser",componentId:1000)
        validEntry.id = "id"
        def saved = validEntry.save(flush:true, failOnError:true)
        assertNotNull saved
        def validEntry2 = new SecurityValue(id:"id",propertyName:"propertyName1",userId:"testUser3")
        validEntry2.id = "id"
        def saved2 = validEntry2.save(flush:true, failOnError:true)
        def all = SecurityValue.findAll()
        assertNull saved
    }
}

Domain:

class SecurityValue {

String id
String propertyName
String userId
//String userName
Long componentId

static constraints =
{
    id unique:true, size: 1..100
    propertyName nullable: false, size: 1..100
    userId nullable: false, size: 1..10
    componentId (
        nullable: true, size: 1..10
    )
}

static mapping =
{ 
    table 'pac_sys.security_value'
    id column:'id', type: 'string', generator: 'assigned'
    version false;
}
}

The issue I'm getting is that the validEntry2.save line is not failing. I added the findAll line to see what data was being stored and it appears that the validEntry is just being overwritten by validEntry2.

Am I missing a mock statement or something else here?


Here is what the test look slike after applying jonnybot's answer. It now has a shouldFail method rather than an assertNull and works properly.

void testUniqueId() {
    def validEntry = new SecurityValue(id:"id",propertyName:"propertyName",userId:"testUser",componentId:1000)
    validEntry.id = "id"
    mockForConstraintsTests(SecurityValue, [validEntry])
    def validEntry2 = new SecurityValue(id:"id",propertyName:"propertyName1",userId:"testUser3")
    validEntry2.id = "id"
    shouldFail(grails.validation.ValidationException)
    {
        def saved2 = validEntry2.save(flush:true, failOnError:true)
    }
}

Upvotes: 3

Views: 1300

Answers (1)

jonnybot
jonnybot

Reputation: 2453

Since what you really want to do is test the constraints, use the mockForConstraintsTests() and validate() methods in your test. See "Testing Constraints" under http://grails.org/doc/2.2.4/guide/testing.html#unitTestingDomains.

For example, you might have

void testUniqueId() {
    def validEntry = new SecurityValue(id:"id",propertyName:"propertyName",userId:"testUser",componentId:1000)
    validEntry.id = "id"
    def saved = validEntry.save(flush:true, failOnError:true)
    assertNotNull saved
    mockForConstraintsTests(SecurityValue, [validEntry])

    def invalidEntry = new SecurityValue(id:"id",propertyName:"propertyName1",userId:"testUser3")
    invalidEntry.id = "id"
    assert !invalidEntry.validate()
}

Upvotes: 4

Related Questions