5
\$\begingroup\$

I have a class Address, a class AddressTest and I am trying to write unit tests for its constructors and getter setters.

Address:

/**
 * The bean Address.
 *
 * @author Sandeep Chatterjee
 * @since 24/8/2015
 */
class Address {

    private BigInteger addressId;

    private String name;

    private String address;

    private String contactNo;

    private String postalCode;

    /**
     * Constructor
     */
    public Address() {
    }


    /**
     * Constructor
     *
     * @param name       Addressee Name
     * @param address    Full Postal Address
     * @param contactNo  Addressee Contact Number
     * @param postalCode Addressee postal code
     */
    private Address(String name, String address, String contactNo, String postalCode) {
        this.addressId = new BigInteger(256, new Random());
        this.name = name;
        this.address = address;
        this.contactNo = contactNo;
        this.postalCode = postalCode;
    }

    /**
     * Static factory
     *
     * @param name       Addressee Name
     * @param address    Full Postal Address
     * @param contactNo  Addressee Contact Number
     * @param postalCode Addressee postal code
     * @return An Address instance
     */
    public static Address createAddress(String name, String address, String contactNo, String postalCode) {
        return new Address(name, address, contactNo, postalCode);
    }

    /* Object overrides */
    @Override
    public String toString() {
        return new ToStringBuilder(this)
                .append("address", address)
                .toString();
    }

    @Override
    public final int hashCode() {
        return Objects.hashCode(addressId);
    }

    @Override
    public final boolean equals(Object object) {
        if (object instanceof Address) {
            Address that = (Address) object;
            return Objects.equal(this.addressId, that.addressId);
        }
        return false;
    }

    /* Accessors and Mutators */

    /**
     * @return Get Address Id
     */
    public BigInteger getAddressId() {
        return addressId;
    }

    /**
     * @param addressId Set Address Id
     */
    public void setAddressId(BigInteger addressId) {
        this.addressId = addressId;
    }

    /**
     * @return Get Addressee Name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name Set Addressee Name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * @return Get Full Postal Address
     */
    public String getAddress() {
        return address;
    }

    /**
     * @param address Set Full Postal Address
     */
    public void setAddress(String address) {
        this.address = address;
    }

    /**
     * @return Get Addressee Contact Number
     */
    public String getContactNo() {
        return contactNo;
    }

    /**
     * @param contactNo Set Addressee Contact Number
     */
    public void setContactNo(String contactNo) {
        this.contactNo = contactNo;
    }

    /**
     * @return Get Addressee postal code
     */
    public String getPostalCode() {
        return postalCode;
    }

    /**
     * @param postalCode Set Addressee postal code
     */
    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }
}

AddressTest:

/**
 * All tests for class Address
 *
 * @author Sandeep Chatterjee
 * @since 24/8/2015
 */
public class AddressTest {

    /**
     * @see [http://www.jqno.nl/equalsverifier/]
     * @see [https://github.com/jqno/equalsverifier/blob/master/README.md]
     */
    @Test
    public void equalsContract() {
        EqualsVerifier.forClass(Address.class)
                .suppress(Warning.NONFINAL_FIELDS, Warning.NULL_FIELDS)
                .verify();
    }


    @Test
    public void testPrivateConstructor() {
        final Constructor<?>[] constructors = Address.class.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
        }
    }


    @Test
    public void testGetterSetterPostalCode() {
        final String postalCode = "456098";
        final Address address = new Address();
        address.setPostalCode("456098");
        Assert.assertEquals(address.getPostalCode(), postalCode);
    }
}

Am I doing this correctly or is there a better way? Any help appreciated.

\$\endgroup\$
0

2 Answers 2

8
\$\begingroup\$
/**
 * Constructor
 */
public Address() {
}

You have just defeated your purpose of making a private constructor... and not only that, it makes it possible to create an Address instance with null fields. Even if this should be possible in your codebase (as used in testGetterSetterPostalCode()), then I will suggest simply sticking to two public constructors - one with the arguments, and one without. The public static createAddress() then becomes unnecessary.

I am also unsure about the viability of testPrivateConstructor()... unit testing should be asserting the behavior of your class's features, not the visibility of its constructors and methods.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Thanks h.j.k. Actually, I was going through Joshua Bloch's Effective Java where in Chapter 2 he mentions "A class can provide its clients with static factory methods instead of, or in addition to, constructors." So, I thought may be it won't harm to provide both. When you say that unit testing should be asserting the behavior of your class's features, not the visibility of its constructors and methods, do you mean or suggest that it is not a good idea to unit test getter setters and constructors? \$\endgroup\$ Commented Aug 24, 2015 at 7:42
  • \$\begingroup\$ There are many threads on SO suugesting that one should write test cases for constructors and getter-setters. :) \$\endgroup\$ Commented Aug 24, 2015 at 7:43
  • 2
    \$\begingroup\$ @SandeepChatterjee even for those kinds of test cases, they probably contain non-trivial logic that applies some kind of input validation - and that will be what the unit testing is for. Unit testing is not about asserting your private constructor remains private when your unit test is running - if that ever becomes false, you'll have other problems to worry about. \$\endgroup\$
    – h.j.k.
    Commented Aug 24, 2015 at 7:49
  • 2
    \$\begingroup\$ @SandeepChatterjee "it won't harm to provide both": yeah, but at the same time you aren't gonna need it... ;) \$\endgroup\$
    – h.j.k.
    Commented Aug 24, 2015 at 7:50
8
\$\begingroup\$

As a more general remark I like to add two excerpts from a book I recently read named "The Art of Unit Testing" by Roy Osherove. It helped me a lot and it is really worth reading – and it also valuable for your question.

Testing Private or Protected Methods

Private or protected methods are usually private for a good reason in the developer’s mind. Sometimes it’s to hide implementation details, so that the implementation can change later without the end functionality changing. It could also be for security-related or IP-related reasons (obfuscation, for example).

When you test a private method, you’re testing against a contract internal to the system, which may well change. Internal contracts are dynamic, and they can change when you refactor the system. When they change, your test could fail because some internal work is being done differently, even though the overall functionality of the system remains the same. For testing purposes, the public contract (the overall functionality) is all that you need to care about. Testing the functionality of private methods may lead to breaking tests, even though the overall functionality is correct. (Section 7.2.1, p.182)

Testing Getters and Setters

Osherove writes that a "unit test is an automated piece of code that invokes the method or class being tested and then checks some assumptions about the logical behavior of that method or class". Logical code is code that has

  • an IF statement
  • a loop
  • switch or case statements
  • calculations or
  • any other type of decision-making code.

And hence he concludes:

Properties (getters/setters in Java) are good examples of code that usually doesn’t contain any logic, and so doesn’t require testing. But watch out: once you add any check inside the property, you’ll want to make sure that logic is being tested. (Section 1.4, p. 12)

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.