31

我正在为我的项目编写单元测试,并试图实现至少 80% 的代码覆盖率。问题是我使用 lombok 的@Data注释来生成 getter 和 setter,当我运行单元测试时,所有这些 getter 和 setter 以及其他方法(如toString,equalshashcode)都被遗漏了,我的代码覆盖率受到了影响。是否有任何解决方法。我一直在搜索这方面的内容,但找不到任何可以提供帮助的东西。对此的任何帮助将不胜感激。

我正在使用 Eclemma 进行代码覆盖率分析。

4

5 回答 5

64

0.8.0 版本@lombok.Generated中,Jacoco 添加了对从报告中过滤掉所有带有注释的方法的支持。您唯一需要更改的是lombok.config使用以下设置添加到项目的根目录:

config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true
  • config.stopBubbling = true告诉 Lombok 这是你的根目录,它不应该在父目录中搜索更多的配置文件(你可以在不同的目录/包中有多个 lombok 配置文件)。
  • lombok.addLombokGeneratedAnnotation = true将为所有 Lombok 生成的方法添加 @lombok.Generated 注释。

就是这样。Jacoco 将过滤 Lombok 自动生成的方法,如果你尽力而为,你的代码覆盖率可能接近 100% :))

于 2018-02-25T08:51:27.033 回答
49

首先, @ Data注解是 @ToString@EqualsAndHashCode@Getter@Setter的组合。

如果您只需要 Lombok 自动创建 getter 和 setter,则可以仅使用@Getter@Setter注释而不是@Data

此外,要使 Lombok 创建的方法不在此范围内,您可以在根目录中创建一个lombok.config文件,并包含以下两行:

config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true

添加此行后,当您转到Sonar时,您会看到这些类被覆盖100%

于 2017-06-16T08:52:33.810 回答
9

当需要 equals 和 hashcode 时,可以使用EqualsVerifier对它们进行非常彻底的单元测试。EqualsVerifier 是一个开源 JUnit 库,可为 equals 和 hashCode 合约的所有部分生成单元测试,即使手动编写测试也无法直接实现。

示例用法:

@Test
public void equalsContract() {
    EqualsVerifier.forClass( MyAwesomeLombokedDataClass.class )
        .suppress( Warning.STRICT_INHERITANCE )
        .verify();
}
于 2017-12-26T08:23:48.670 回答
2

在根级别创建一个 lombok.config 文件并添加此代码

config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true

将被代码覆盖忽略

于 2020-08-18T18:03:51.223 回答
0

您可以尝试EqualsVerifier
如果您想手动尝试,这可能会有所帮助(我的学习笔记)。这也涵盖了 96% 的突变测试:

@Getter
@Setter
@Builder
@ToString
@Component
@EqualsAndHashCode
@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES)
public class ValidationEntity {
    private boolean valid;
    private int lineNumber;
    private int columnNumber;
    private String inputMessage;
    private String validationMessage;

    @JsonCreator
    ValidationEntity(@JsonProperty("valid") final boolean valid, @JsonProperty("lineNumber") final int lineNumber,
                     @JsonProperty("columnNumber") final int columnNumber, @JsonProperty("inputMessage") final String inputMessage,
                     @JsonProperty("validationMessage") final String validationMessage) {
        this.valid = valid;
        this.lineNumber = lineNumber;
        this.columnNumber = columnNumber;
        this.inputMessage = inputMessage;
        this.validationMessage = validationMessage;
    }

    public static ValidationEntityBuilder builder(String inputMessage) {
        return new ValidationEntityBuilder().inputMessage(inputMessage);
    }
}

这是我的测试课:

/**
 * Validation Response Entity has the response details for all configured editor methods.
 * Tests are based on:
 * https://www.artima.com/lejava/articles/equality.html
 */
public class ValidationEntityTest {

    @Test
    public void newValidationEntityWithBuilder_whenEqual_ThenTrue() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity z = x;

        //reflexive: for any non-null value x, the expression x.equals(x) should return true.
        Assert.assertTrue(x.equals(x));
        //symmetric: for any non-null values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
        Assert.assertTrue(x.equals(y) && y.equals(x));
        //transitive: for any non-null values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
        Assert.assertTrue(x.equals(z) && y.equals(z) && x.equals(y));
        //consistent: for any non-null values x and y, multiple invocations of x.equals(y) should consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
        Assert.assertTrue(x.equals(y) && x.equals(y) && x.equals(y) && x.equals(y));
        //Null check: for any non-null value x, x.equals(null) should return false.
        Assert.assertFalse(x.equals(null));

        Assert.assertEquals(x, y);
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
        Assert.assertEquals(x.getInputMessage(), y.getInputMessage());
        Assert.assertEquals(x.getValidationMessage(), y.getValidationMessage());
        Assert.assertEquals(x.getLineNumber(), y.getLineNumber());
        Assert.assertEquals(x.getColumnNumber(), y.getColumnNumber());
        Assert.assertEquals(x.isValid(), y.isValid());
    }

    @Test
    public void newValidationEntityWithBuilder_whenNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("Custom Input Message").lineNumber(1).columnNumber(2).valid(false).validationMessage("Custom Validation Message").build();

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
        Assert.assertNotEquals(x.getInputMessage(), y.getInputMessage());
        Assert.assertNotEquals(x.getValidationMessage(), y.getValidationMessage());
        Assert.assertNotEquals(x.getLineNumber(), y.getLineNumber());
        Assert.assertNotEquals(x.getColumnNumber(), y.getColumnNumber());
        Assert.assertNotEquals(x.isValid(), y.isValid());
    }

    @Test
    public void newValidationEntityWithBuilder_whenBothAreEqualAndObjectInstances_ThenTrue() {
        Object x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        Object y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();

        Assert.assertTrue(x.equals(y) && y.equals(x));
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityStringWithBuilder_whenSameInstanceToStringsAreCompared_ThenTrue() {
        String x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").toString();
        String y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").toString();

        Assert.assertEquals("ValidationEntity.ValidationEntityBuilder(valid=true, lineNumber=11, columnNumber=22, inputMessage=inputMessage, validationMessage=Validation Successful)", x);
        Assert.assertEquals("ValidationEntity.ValidationEntityBuilder(valid=true, lineNumber=11, columnNumber=22, inputMessage=inputMessage, validationMessage=Validation Successful)", y);
    }

    @Test
    public void newValidationEntityWithBuilder_whenOneIsInstanceAndOtherString_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        String y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build().toString();

        Assert.assertFalse(x.equals(y));
        Assert.assertFalse(y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenOneIsInstanceAndOtherOneIsAChild_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();

        class ValidationEntityExtended extends ValidationEntity {
            String additionalDetail;

            public String getAdditionalDetail() {
                return this.additionalDetail;
            }

            public void setAdditionalDetail(final String additionalDetail) {
                this.additionalDetail = additionalDetail;
            }

            ValidationEntityExtended(@JsonProperty("valid") final boolean valid, @JsonProperty("lineNumber") final int lineNumber,
                                     @JsonProperty("columnNumber") final int columnNumber, @JsonProperty("inputMessage") final String inputMessage,
                                     @JsonProperty("validationMessage") final String validationMessage, String additionalDetail) {
                super(true, 11, 22, "inputMessage", "Validation Successful");
                this.additionalDetail = additionalDetail;
            }

            @Override
            public boolean equals(Object other) {
                boolean result = false;
                if (other instanceof ValidationEntityExtended) {
                    ValidationEntityExtended that = (ValidationEntityExtended) other;
                    result = (that.canEqual(this) && this.additionalDetail.equals(that.additionalDetail) && super.equals(that));
                }
                return result;
            }

            @Override
            public int hashCode() {
                return (41 * super.hashCode() + additionalDetail.hashCode());
            }

            @Override
            public boolean canEqual(Object other) {
                return (other instanceof ValidationEntityExtended);
            }

            @Override
            public String toString() {
                return "ValidationEntityExtended(valid=" + this.isValid() + ", lineNumber=" + this.getLineNumber() + ", columnNumber=" + this.getColumnNumber() + ", inputMessage=" + this.getInputMessage() + ", validationMessage=" + this.getValidationMessage() + ", additionalDetail=" + this.getAdditionalDetail() + ")";
            }
        }
        ValidationEntityExtended validationEntityExtended = new ValidationEntityExtended(true, 11, 22, "inputMessage", "Validation Successful", "additionalDetail");
        Assert.assertFalse(x.equals(validationEntityExtended));
        Assert.assertFalse(validationEntityExtended.equals(x));
        Assert.assertNotEquals(x.hashCode(), validationEntityExtended.hashCode());
        Assert.assertNotEquals(x.toString(), validationEntityExtended.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenEachMethodIsEqual_ThenTrue() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();

        Assert.assertTrue(x.equals(y) && y.equals(x));
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
        Assert.assertEquals(x.getInputMessage(), y.getInputMessage());
        Assert.assertEquals(x.getValidationMessage(), y.getValidationMessage());
        Assert.assertEquals(x.getLineNumber(), y.getLineNumber());
        Assert.assertEquals(x.getColumnNumber(), y.getColumnNumber());
        Assert.assertEquals(x.isValid(), y.isValid());
    }

    @Test
    public void newValidationEntityWithBuilder_whenInputMessageNullForOne_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder(null).lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();

        Assert.assertNotEquals(x, y);
        Assert.assertNotEquals(y, x);
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenInputMessageNullForBoth_ThenTrue() {
        ValidationEntity x = ValidationEntity.builder(null).lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder(null).lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();

        Assert.assertEquals(x, y);
        Assert.assertEquals(y, x);
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenInputMessageNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Custom Input Message").build();

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenValidNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        y.setValid(false);

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenLineNumberNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        y.setLineNumber(1);

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenColumnNumberNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        y.setColumnNumber(2);

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenValidationMessageNullForOne_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage(null).build();

        Assert.assertNotEquals(x, y);
        Assert.assertNotEquals(y, x);
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenValidationMessageBothNull_ThenTrue() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage(null).build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage(null).build();

        Assert.assertEquals(x, y);
        Assert.assertEquals(y, x);
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithBuilder_whenValidationMessageNotEqual_ThenFalse() {
        ValidationEntity x = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Validation Successful").build();
        ValidationEntity y = ValidationEntity.builder("inputMessage").lineNumber(11).columnNumber(22).valid(true).validationMessage("Custom Validation Message").build();

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
    }

    @Test
    public void newValidationEntityWithAllArgsConstructor_whenEqual_ThenTrue() {
        ValidationEntity x = new ValidationEntity(true, 11, 22, "inputMessage", "Validation Successful");
        ValidationEntity y = new ValidationEntity(true, 11, 22, "inputMessage", "Validation Successful");

        Assert.assertTrue(x.equals(y) && y.equals(x));
        Assert.assertEquals(x.hashCode(), y.hashCode());
        Assert.assertEquals(x.toString(), y.toString());
        Assert.assertEquals(x.getInputMessage(), y.getInputMessage());
        Assert.assertEquals(x.getValidationMessage(), y.getValidationMessage());
        Assert.assertEquals(x.getLineNumber(), y.getLineNumber());
        Assert.assertEquals(x.getColumnNumber(), y.getColumnNumber());
        Assert.assertEquals(x.isValid(), y.isValid());
    }


    @Test
    public void newValidationEntityWithAllArgsConstructor_whenNotEqual_ThenFalse() {
        ValidationEntity x = new ValidationEntity(true, 11, 22, "inputMessage", "Validation Successful");
        ValidationEntity y = new ValidationEntity(false, 1, 1, "Custom inputMessage", "Custom Validation Successful");

        Assert.assertFalse(x.equals(y) && y.equals(x));
        Assert.assertNotEquals(x.hashCode(), y.hashCode());
        Assert.assertNotEquals(x.toString(), y.toString());
        Assert.assertNotEquals(x.getInputMessage(), y.getInputMessage());
        Assert.assertNotEquals(x.getValidationMessage(), y.getValidationMessage());
        Assert.assertNotEquals(x.getLineNumber(), y.getLineNumber());
        Assert.assertNotEquals(x.getColumnNumber(), y.getColumnNumber());
        Assert.assertNotEquals(x.isValid(), y.isValid());
    }
}
于 2020-06-07T20:22:41.843 回答