Java Reference
In-Depth Information
G
public void
testSaveUserWithTelephone()
throws
Exception {
User user = newUserWithTelephone();
beginTransaction();
em.persist(user);
commitTransaction();
}
As explained earlier, we opted for manual transaction control, so the test case explic-
itly starts and finishes the transaction.
Because we're testing the entity mappings and not the real persistence layer code such
as
DAO
implementations, we deal with the persistence manager directly.
Once the object is read from the database, we assert that it has the expected values,
using our old friend
EntitiesHelper
F
;
id
and
phoneId
(which are defined in the
superclass and have the initial value of 1) are updated to reflect the objects that were
loaded from the database. If they aren't updated, the next test case could fail (if it
saves objects, which is the case in our example).
The test case for saving an entity is pretty much orthogonal to the load entity test case;
nothing new here.
B
,
D
C
E
G
Although these tests run fine and pass, the way the
ID
s (
id
and
phoneId
) are handled
is far from elegant and presents many flaws. For instance, if a test case fails, the
ID
s
aren't updated, and then other tests running after it will fail as well. Sure, a
try/
finally
block would fix this particular issue, but that would make the test even uglier
and more verbose. Another problem is that
testSaveUserWithTelephone()
doesn't
update the
ID
s (because its dataset assertion would fail), so a third test case would
probably fail.
What should we do to solve these
ID
issues? Well, don't throw the topic away
(yet)—a solution for this problem follows.
18.4.1
Integrating test cases with JPA ID generators
In
JPA
, every persistent entity needs an
ID
, which is the equivalent of a primary key.
When a new entity is persisted, the
JPA
engine must set its
ID
, and how its value is deter-
mined depends on the mapping. For instance, our
User
class has the following mapping:
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private long id;
The
@Id
annotation indicates this attribute represents the entity's primary key, and
@GeneratedValue
defines how its value is obtained when the entity is persisted.
AUTO
in
this case means we left the decision to the
JPA
vendor, which will pick the best strate-
gies depending on what the target database supports. Other values are
IDENTITY
(for
databases that support autogenerated primary keys),
SEQUENCE
(uses database sequences,
where supported), and
TABLES
(uses one or more tables only for the purpose of
generating primary keys). A fifth option would be omitting
@GeneratedValue
, which
means the user (and not the
JPA
engine) is responsible for setting the
ID
s. In most cases,
AUTO
is the best choice; it's the default option for the
@GeneratedValue
annotation.