• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / javabean-tester / 3227

16 Feb 2026 12:20AM UTC coverage: 87.5% (-0.4%) from 87.852%
3227

push

github

hazendaz
Found possible bug in handling, its not always possible to be purist on current code for equals

noted what the expectation was, its not achieved, so just allow it through.  This was an existing problem that the tests didn't catch due to sub objects.  I had added a test when looking at lombok builder pattern and stumbled onto it.  In the equals only tests, its actually doing almost same thing.  This area is known not strong enough and is additionally using equals verifier to try to compensate.

285 of 331 branches covered (86.1%)

5 of 5 new or added lines in 1 file covered. (100.0%)

67 existing lines in 6 files now uncovered.

525 of 600 relevant lines covered (87.5%)

0.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.62
/src/main/java/com/codebox/bean/JavaBeanTester.java
1
/*
2
 * SPDX-License-Identifier: Apache-2.0
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2012-2026 hazendaz
6
 *
7
 * Portions of initial baseline code (getter/setter test) by Rob Dawson (CodeBox)
8
 */
9
package com.codebox.bean;
10

11
import com.codebox.util.LombokBuilderUtil;
12

13
import java.lang.reflect.Modifier;
14

15
import net.bytebuddy.ByteBuddy;
16
import net.bytebuddy.NamingStrategy;
17
import net.bytebuddy.description.NamedElement;
18
import net.bytebuddy.description.modifier.Visibility;
19
import net.bytebuddy.description.type.TypeDescription;
20
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
21
import net.bytebuddy.implementation.HashCodeMethod;
22
import net.bytebuddy.implementation.MethodDelegation;
23
import net.bytebuddy.implementation.ToStringMethod;
24
import net.bytebuddy.implementation.bind.annotation.Argument;
25
import net.bytebuddy.implementation.bind.annotation.This;
26
import net.bytebuddy.matcher.ElementMatchers;
27

28
/**
29
 * This helper class can be used to unit test the get/set/equals/canEqual/toString/hashCode methods of JavaBean-style
30
 * Value Objects.
31
 */
32
public enum JavaBeanTester {
1✔
33

34
    // Private Usage
35
    ;
36

37
    /**
38
     * Configure JavaBeanTester using Fluent API.
39
     *
40
     * @param <T>
41
     *            the generic type
42
     * @param clazz
43
     *            the clazz
44
     *
45
     * @return A builder implementing the fluent API to configure JavaBeanTester
46
     */
47
    public static <T> JavaBeanTesterBuilder<T, ?> builder(final Class<T> clazz) {
48
        // If class is final, use Object.class for comparison needs
49
        if (Modifier.isFinal(clazz.getModifiers())) {
1✔
50
            return new JavaBeanTesterBuilder<>(clazz, Object.class);
1✔
51
        }
52

53
        // Lombok builder not supported by byte buddy, do not attempt to build extension class
54
        if (LombokBuilderUtil.getLombokBuilderMethod(clazz) != null) {
1✔
55
            return builder(clazz, null);
1✔
56
        }
57

58
        // Build extension from class using byte buddy
59
        Class<? extends T> loaded = new ByteBuddy().with(new NamingStrategy.AbstractBase() {
1✔
60
            @Override
61
            protected String name(TypeDescription superClass) {
62
                return clazz.getPackageName() + ".ByteBuddyExt" + superClass.getSimpleName();
1✔
63
            }
64
        }).subclass(clazz).method(ElementMatchers.isEquals())
1✔
65
                .intercept(MethodDelegation.to(InstanceOfEqualsInterceptor.class)).method(ElementMatchers.isHashCode())
1✔
66
                .intercept(HashCodeMethod.usingSuperClassOffset()).method(ElementMatchers.isToString())
1✔
67
                .intercept(ToStringMethod.prefixedBySimpleClassName()).method(ElementMatchers.named("canEqual"))
1✔
68
                .intercept(MethodDelegation.to(CanEqualInterceptor.class))
1✔
69
                .defineField("javabeanExtension", String.class, Visibility.PACKAGE_PRIVATE).make()
1✔
70
                .load(clazz.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER).getLoaded();
1✔
71

72
        // Builder with proper extension class
73
        return builder(clazz, loaded);
1✔
74
    }
75

76
    /**
77
     * Configure JavaBeanTester using Fluent API.
78
     *
79
     * @param <T>
80
     *            the generic type
81
     * @param <E>
82
     *            the element type
83
     * @param clazz
84
     *            the clazz
85
     * @param extension
86
     *            the extension
87
     *
88
     * @return A builder implementing the fluent API to configure JavaBeanTester
89
     */
90
    public static <T, E> JavaBeanTesterBuilder<T, E> builder(final Class<T> clazz, final Class<E> extension) {
91
        return new JavaBeanTesterBuilder<>(clazz, extension);
1✔
92
    }
93

94
    /**
95
     * The Class CanEqualInterceptor.
96
     */
97
    public final static class CanEqualInterceptor {
98

99
        /**
100
         * Prevents instantiation a new can equal interceptor.
101
         */
UNCOV
102
        CanEqualInterceptor() {
×
103
            // Private constructor to prevent instantiation
UNCOV
104
        }
×
105

106
        /**
107
         * Can Equal Interceptor.
108
         *
109
         * @param object
110
         *            The object to check can equals
111
         * @return boolean of can equals
112
         */
113
        public static boolean canEqual(final Object object) {
114
            return object instanceof NamedElement.WithRuntimeName;
1✔
115
        }
116

117
    }
118

119
    /**
120
     * The Class InstanceOfEqualsInterceptor.
121
     */
122
    public final static class InstanceOfEqualsInterceptor {
123

124
        /**
125
         * Prevents instantiation a new instance of equals interceptor.
126
         */
UNCOV
127
        InstanceOfEqualsInterceptor() {
×
128
            // Private constructor to prevent instantiation
UNCOV
129
        }
×
130

131
        /**
132
         * Equals.
133
         *
134
         * @param self
135
         *            the self
136
         * @param other
137
         *            the other
138
         * @return true, if successful
139
         */
140
        public static boolean equals(@This Object self, @Argument(0) Object other) {
141
            if (self == other) {
1✔
142
                return true;
1✔
143
            }
144
            if ((other == null) || (!self.getClass().isInstance(other) && !other.getClass().isInstance(self))) {
1!
145
                return false;
1✔
146
            }
147
            return self.hashCode() == other.hashCode();
1✔
148
        }
149
    }
150

151
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc