UserEntity具有以下关联:
ManyToMany-城市
ManyToMany-ActivityCategory
ManyToOne-UserType
@Test
public void testCreateNotExistingEmail() {
UserTypeEntity userTypeEntity = userTypeDao.find(1L);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String password = encoder.encode("123456");
List<CityEntity> cityEntities = new ArrayList<>();
cityEntities.add(cityDao.find(1L));
cityEntities.add(cityDao.find(2L));
List<ActivityCategoryEntity> activityCategoryEntities = new ArrayList<>();
activityCategoryEntities.add(activityCategoryDao.find(4L));
activityCategoryEntities.add(activityCategoryDao.find(5L));
UserEntity userEntity = new UserEntity();
userEntity.setEmail("user@domain.com");
userEntity.setIsActive(true);
userEntity.setPassword(password);
userEntity.setUserTypeEntity(userTypeEntity);
userEntity.setCities(cityEntities);
userEntity.setActivityCategories(activityCategoryEntities);
userDao.create(userEntity);
UserEntity userEntityCreated = userDao.find(userEntity.getId());
Assert.assertNotNull(userEntityCreated);
Assert.assertEquals(2, userEntityCreated.getCities().size());
Assert.assertEquals(2, userEntityCreated.getActivityCategories().size());
}
我在测试中还能做得更好吗?
#1 楼
略作说明:您的测试名为testCreateNotExistingEmail
。 @Test
批注已经表明这是一个测试,因此不必在方法名本身中重复。补充:我喜欢以
[UnitOfWorkName]_[ScenarioUnderTest]_[ExpectedBehaviour]
的格式构造测试。当我查看代码时,很难说出测试的确切功能,因为方法名指示不存在的电子邮件的某些信息,这使我不得不考虑某个地方处理的异常。
但是,当我查看代码时,根本看不到任何断言。实际上,我只看到一封电子邮件在看似无关的上下文中使用过一次。
需要一些澄清:更好的方法名称。现在,当在大量测试中测试失败时,您可以在深入研究之前更精确地指出哪种情况出了问题。
#2 楼
测试方法的名称是testCreateNotExistingEmail
,但我不知道它与您要测试的内容有什么关系。测试的目的是什么?如果没有其他用户实体具有相同的电子邮件,是否可以成功创建用户实体?如果是这样,那么我将改为执行以下操作:
@Test
public void testCreateNotExistingEmail() {
UserEntity userEntity = new UserEntity();
userEntity.setEmail("nonexistent@domain.com");
userDao.create(userEntity);
}
@Test(expected=UniqueKeyIntegrityException.class)
public void testCannotCreateWithExistingEmail() {
String email = "user@domain.com";
// or something like this:
Assert.assertNull(userDao.findByEmail(email));
UserEntity userEntity = new UserEntity();
userEntity.setEmail(email);
userDao.create(userEntity); // success
userEntity.setEmail(email);
userDao.create(userEntity); // throws
}
是否需要为测试设置所有这些字段?如果不是,则忽略它们。例如,如果没有密码的用户有效,则在此测试用例中不要设置密码,因为这是不必要的。单元测试应尽可能地短。我将针对
UserEntity
本身的测试与验证正确的关系(与城市和类别)的测试分开。您对关系(与城市和类别)的测试可能更多严格。最好在
userEntity
和userEntityCreated
中比较每个城市和每个类别的ID。我将使用单独的测试方法:一项针对城市关系的测试
一项针对类别关系的测试
为了增加安全性,我还要对City + category进行另一项测试。这可以简化,例如仅比较大小即可。
注意潜在的副作用。例如,如果您有多个使用
userDao
的测试,请确保在@Before
中重新初始化,以使所有测试均以相同的设置开始,并且彼此之间没有副作用。#3 楼
已经给出的答案是很好的答案,但我发现有些地方没有说。第一:
您的测试确实包含一些数据库,可能是在生成时您在服务器上测试还是在开发数据库上。
您是否对
@Transactional
进行了类培训? br />为什么:您将确保在方法结束时回滚您的数据库。
这意味着将数据库设置为与方法开始时一样的原始状态。
测试的执行顺序可能会有所变化,因此可能导致先前/进一步的测试失败。
第二个:
为什么在失败时不提供带有断言的文本消息,如下所示:消息,因此您可以直接知道断言在您的方法中失败了。
希望可以为您提供进一步的帮助。
评论
\ $ \ begingroup \ $
好点。所有测试均继承自TestDaoSetup类,该类具有ContextConfiguration(...这里的配置位置...),TransactionConfiguration和Transactional批注。我喜欢你的第二点。我会肯定使用它。不幸的是,我无法将更多答案标记为正确,他们应该将其真正添加到此站点。
\ $ \ endgroup \ $
–user40964
14年4月19日在19:13
\ $ \ begingroup \ $
不必这样做,我们在这里可以互相帮助;)
\ $ \ endgroup \ $
– chillworld
14年4月19日在19:18
评论
\ $ \ begingroup \ $
谢谢您的建议。我同意,该方法的名称可能会更好,但是您建议的名称确实很长。因此,我认为最好将信息放入Javadoc注释中。至少比“ TestCreationOfAUserWithEmail ...”具有更好的可读性,例如“使用电子邮件创建用户...”。
\ $ \ endgroup \ $
–user40964
2014年4月19日在18:09
\ $ \ begingroup \ $
如果第一个单词未经测试,则不管是否存在@Test批注,某些IDE(会想到IntelliJ)都不喜欢它。海事组织这对他们来说是个坏主意,但有时我们必须忍受自己拥有的东西
\ $ \ endgroup \ $
– Robert Snyder
2014年4月19日在18:09
\ $ \ begingroup \ $
为什么方法名称有多长会很重要?这是您永远不会称呼自己的事情。名称所要做的只是显示在您的测试结果窗口中,并尽可能地具有描述性,通过缩短它不会有任何好处。
\ $ \ endgroup \ $
– Jeroen Vannevel
2014年4月19日在18:11
\ $ \ begingroup \ $
@JeroenVannevel我明白你的意思。在这种情况下,最好使用更具描述性的名称。
\ $ \ endgroup \ $
–user40964
2014年4月19日在18:17
\ $ \ begingroup \ $
@Yoda:C#习惯,在Java中应该是小写。我的错
\ $ \ endgroup \ $
– Jeroen Vannevel
2014年4月19日在18:59