Java 单元测试覆盖率数字不匹配
-
13-09-2019 - |
题
下面是我在使用 Java Google App Engine 构建的 Web 应用程序中编写的一个类。我已经使用 TestNG 编写了单元测试,并且所有测试都通过了。然后,我在 Eclipse 中运行 EclEmma 以查看代码的测试覆盖率。所有函数都显示 100% 的覆盖率,但整个文件显示的覆盖率约为 27%。73% 未覆盖的代码从何而来?
谁能帮助我了解 EclEmma 的工作原理以及为什么我会遇到数字差异?
package com.skaxo.sports.models;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;
@PersistenceCapable(identityType= IdentityType.APPLICATION)
public class Account {
@PrimaryKey
@Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
private Long id;
@Persistent
private String userId;
@Persistent
private String firstName;
@Persistent
private String lastName;
@Persistent
private String email;
@Persistent
private boolean termsOfService;
@Persistent
private boolean systemEmails;
public Account() {}
public Account(String firstName, String lastName, String email) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public Account(String userId) {
super();
this.userId = userId;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean acceptedTermsOfService() {
return termsOfService;
}
public void setTermsOfService(boolean termsOfService) {
this.termsOfService = termsOfService;
}
public boolean acceptedSystemEmails() {
return systemEmails;
}
public void setSystemEmails(boolean systemEmails) {
this.systemEmails = systemEmails;
}
}
下面是上述类的测试代码。
package com.skaxo.sports.models;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.assertFalse;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class AccountTest {
@Test
public void testId() {
Account a = new Account();
a.setId(1L);
assertEquals((Long) 1L, a.getId(), "ID");
a.setId(3L);
assertNotNull(a.getId(), "The ID is set to null.");
}
@Test
public void testUserId() {
Account a = new Account();
a.setUserId("123456ABC");
assertEquals(a.getUserId(), "123456ABC", "User ID incorrect.");
a = new Account("123456ABC");
assertEquals(a.getUserId(), "123456ABC", "User ID incorrect.");
}
@Test
public void testFirstName() {
Account a = new Account("Test", "User", "test@example.com");
assertEquals(a.getFirstName(), "Test",
"User first name not equal to 'Test'.");
a.setFirstName("John");
assertEquals(a.getFirstName(), "John",
"User first name not equal to 'John'.");
}
@Test
public void testLastName() {
Account a = new Account("Test", "User", "test@example.com");
assertEquals(a.getLastName(), "User",
"User last name not equal to 'User'.");
a.setLastName("Doe");
assertEquals(a.getLastName(), "Doe",
"User last name not equal to 'Doe'.");
}
@Test
public void testEmail() {
Account a = new Account("Test", "User", "test@example.com");
assertEquals(a.getEmail(), "test@example.com",
"User email not equal to 'test@example.com'.");
a.setEmail("john@example.com");
assertEquals(a.getEmail(), "john@example.com",
"User email not equal to 'john@example.com'.");
}
@Test
public void testAcceptedTermsOfService() {
Account a = new Account();
a.setTermsOfService(true);
assertTrue(a.acceptedTermsOfService(),
"Accepted Terms of Service not true.");
a.setTermsOfService(false);
assertFalse(a.acceptedTermsOfService(),
"Accepted Terms of Service not false.");
}
@Test
public void testAcceptedSystemEmails() {
Account a = new Account();
a.setSystemEmails(true);
assertTrue(a.acceptedSystemEmails(), "System Emails is not true.");
a.setSystemEmails(false);
assertFalse(a.acceptedSystemEmails(), "System Emails is not false.");
}
}
解决方案
这是一个猜测,但基于 Javadoc 持久能力 看起来该类由 JDO 增强器与附加代码交织在一起以实现该接口。如果是这种情况,您的测试很可能未涵盖附加代码。如果删除注释并再次运行测试,您是否会看到预期的覆盖范围?
来自 Javadoc:
在参考实现中,JDO 增强器在将类加载到运行时环境之前修改该类以实现 PersistenceCapable。参考增强器还添加代码来实现 PersistenceCapable 定义的方法。
您也可以尝试使用反编译器,例如 杰德 检查编译后的类,以验证该类是否确实在编译时(或作为预处理)与其他方法交织在一起。再次来自 Javadoc:
PersistenceCapable 接口中的额外方法可以通过预处理 .java 文件生成,也可以直接从工具生成。JDO 没有指定生成额外方法的确切技术。
不隶属于 StackOverflow