Grails:在单元测试期间从服务中的Datamodel对象获取IndexOutOfBoundsException

时间:2012-06-13 12:51:41

标签: unit-testing grails gorm grails-2.0

我有一个简单的Customer + PaswordReset数据模型。

在我的PasswordService中,我调用PasswordReset.findByUsername()和save(),它运行正常。

然后我创建了具有@Mock([Customer,PasswordReset])的PasswordServiceTests 在该测试中,我创建了一个新的Customer对象并使用Customer.save并使用PasswordReset.findByUsername()。两者都很好。

测试调用service.initatePasswordReset()(PasswordService),它成功使用了Customer.findByUsername()和PasswordReset.save()。

在测试中,我然后调用PasswordReset.findByUsername(...)并找到service.initiateReset()创建的对象。

但是当我调用另一个方法:service.performReset(),它通过使用Customer.findByUsername(..)成功加载客户对象时,修改客户密码字段并尝试执行customer.save()

以下错误是由PasswordService中的customer.save()引起的。有谁能告诉我出了什么问题?

  

java.lang.IndexOutOfBoundsException:Index:1,Size:1       at java.util.ArrayList.rangeCheck(ArrayList.java:604)       at java.util.ArrayList.remove(ArrayList.java:445)       at org.grails.datastore.mapping.simple.engine.SimpleMapEntityPersister $ 1.deindex(SimpleMapEntityPersister.groovy:101)       在org.grails.datastore.mapping.engine.NativeEntryEntityPersister.updatePropertyIndi​​ces(NativeEntryEntityPersister.java:1200)       在org.grails.datastore.mapping.engine.NativeEntryEntityPersister.access $ 100(NativeEntryEntityPersister.java:55)       在org.grails.datastore.mapping.engine.NativeEntryEntityPersister $ 4.run(NativeEntryEntityPersister.java:958)       在org.grails.datastore.mapping.core.impl.PendingOperationExecution.executePendingOperation(PendingOperationExecution.java:36)       在org.grails.datastore.mapping.core.AbstractSession.flushPendingOperations(AbstractSession.java:323)       在org.grails.datastore.mapping.core.AbstractSession.flushPendingUpdates(AbstractSession.java:302)       在org.grails.datastore.mapping.core.AbstractSession.flush(AbstractSession.java:240)       在org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy:168)       在org.grails.datastore.gorm.GormInstanceApi $ _save_closure4.doCall(GormInstanceApi.groovy:143)       在org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:301)       在org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:34)       在org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:142)       在com.foo.services.PasswordService.performPasswordReset(PasswordService.groovy:33)       在com.foo.services.PasswordServiceTests.testResetPassword(PasswordServiceTests.groovy:47)

PasswordServiceTest.groovy

@TestFor(PasswordService)
@Mock([Customer, PasswordReset])
class PasswordServiceTests {

void setUp() {
    mockCodec(MD5Codec)
   // mockService(CustomerRegistrationService)
}

void testResetPassword() {
        Customer c = CustomerRegistrationServiceTests.makePrivateCustomer()
        c.sumUnpaidInvoices = 0
        c.sumOverdueInvoices = 0
        c.password = service.hashPassword(c)
        c.customerType = CustomerType.NormalCustomer.value

        c.save(flush: true);
        assertEquals("Mock DB does not contain 1 customer", 1, Customer.list().size())

        service.initiatePasswordReset(c.username)

        def pwReset = PasswordReset.findByUsername(c.username)
        println("psreset saved: " + pwReset.username + " / " + pwReset.code)
        assertEquals(c.username, pwReset.username)

        service.performPasswordReset(c.username, "test"); // CALLS METHOD BELOW
    }
}

PasswordService.groovy中的方法:

def performPasswordReset(String username, String newPassword) {
    Customer customer = Customer.findByUsername(username)
    if(customer != null) {
        customer.password = newPassword;
        customer.password = hashPassword(customer);

        customer.save(flush: true); // CAUSES THE ERROR
        ....
    }
}

2 个答案:

答案 0 :(得分:2)

我通过在服务中删除对customer.save()的调用来修复此问题,它不是必需的,即使没有customer.save,密码仍然会在您更改时自动存储到数据库中(customer.password =“foo” “)。

答案 1 :(得分:0)

看起来这个特殊错误与

并不真正相关
customer.save(flush: true);

我会说hibernate还有其他东西需要保留(以前的任何“非刷新保存”)并且失败了。