I marked an immutable data model class as final to make sure the only way to change its values is to create a new instance. (Unfortunately, the fields cannot be final because they needs to be populated by Hibernate.)
This worked well until I wanted to check another class throws the correct exception when called with an invalid instance of the model. The constructor of the model validates the arguments so reflection must be used to set the fields. This is extremely clumsy since the model have quite a few fields and the field names have to be hard-coded.
I can’t mock the model either due to it being final. (Is it also debatable whether an interface should be used to enable mocking while keeping the class immutable. By having an interface, there’s no way to programmatically mandate the methods must return the same value throughout the life of the instance.)
What do people usually do in this case? Is there any standard approach to this?
Generally speaking, you shouldn’t want to mock data objects. Data objects should have no logic and no external dependencies, so there’s not really much use to mocking the objects. Instead make it very easy to create fake instances that you can populate in methods as you’d like.
Furthermore, there are a few other reasons you might want to avoid treating a Hibernate-persisted object as immutable:
finalsemantics.My advice? If you need more immutability and data validation guarantees than a Hibernate DAO can grant you, then create a real final immutable class with final fields (or a private constructor and static factory method), and then make a constructor (or static factory method) that copies in values from your Hibernate DAO.
If you decide this option, you are stuck with the overhead of having two data objects that change roughly in parallel, but you also get the benefit of separating concerns (in case the Hibernate object should diverge) and the ease of a truly-immutable, equals-and-hashcode-overriding, session-agnostic, guaranteed-valid object that you can easily create for tests.