DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Languages
  4. Testing an Object's Internal State with PowerMock

Testing an Object's Internal State with PowerMock

Roger Hughes user avatar by
Roger Hughes
·
Oct. 27, 11 · Interview
Like (0)
Save
Tweet
Share
18.58K Views

Join the DZone community and get the full member experience.

Join For Free

Most unit testing focuses on testing an object’s behaviour in order to prove that it works. This is achieved by writing a JUnit test that calls an object’s public methods and then testing that the return values from these calls match some previously defined set of expected values. This is a very common and successful technique; however, it shouldn't be forgotten that objects also exhibit state; something that is, by virtue of the fact that it’s hidden, often overlooked.

Grady Booch’s 1994 Book Object Oriented Analysis and Design, which I first read in the summer of 1995 defines an object’s state in the following way:

The state of an object encompasses all of the (usually static) properties of the object plus the current (usually dynamic) values of each of these properties.

He defines the difference between static state and dynamic state using a vending machine example. Static state is exhibited by the way that the machine is always ready to take your money, whilst dynamic state is how much of your money it’s got at any given instance.

I suspect that at this point, you’ll quite rightly argue that explicit behavioural tests do test an object’s state by virtue of the fact that a given method call returned the correct result and that to get the correct result the object’s state had to also be correct... and I’ll agree. There are, however, those very few cases where classic behavioural testing isn’t applicable. This occurs when a public method call has no output and does nothing to an object except change its state. An example of this would be a method that returned void or a constructor. For example, given a method with the following signature:
  public void init(); 

…how do you ensure it’s done its job? It turns out that there are several methods you can use to achieve this...
  • Add lots of getter methods to your class. This is not a particularly good idea, as you’re simply loosening encapsulation by the back door.
  • Relax encapsulation: make private instance variables package private. A very debatable thing to do. You could pragmatically argue that having well tested, correct and reliable code may be better than having a high degree of encapsulation, but I’m not too sure here. This may be a short term fix, but could lead to all kinds of problems in the future and there should be a way of writing well tested, correct and reliable code that doesn’t include breaking an object’s encapsulation
  • Write some code that uses reflection to access an object’s internal state. This is the best idea to date. The down side is that it’s a fair amount of effort and requires a reasonable amount of programming competence.
  • Use PowerMock’s Whitebox testing class to do the hard work for you.
The following fully contrived scenario demonstrates the use of PowerMock’s Whitebox class. It takes a very simple AnchorTag <a> class that will build an anchor tag after testing that an input URL string is valid.

public class AnchorTag {

  private static final Logger logger = LoggerFactory.getLogger(AnchorTag.class);

  /** Use the regex to figure out if the argument is a URL */
  private final Pattern pattern = Pattern.compile("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$");

  /**
   * A public method that uses the private method
   */
  public String getTag(String url, String description) {

    validate(url, description);
    String anchor = createNewTag(url, description);

    logger.info("This is the new tag: " + anchor);
    return "The tag is okay";
  }

  /**
   * A private method that's used internally, but is complex enough to require testing in its own right
   */
  private void validate(String url, String description) {

    Matcher m = pattern.matcher(url);

    if (!m.matches()) {
      throw new IllegalArgumentException();
    }
  }

  private String createNewTag(String url, String description) {
    return "<a href=\"" + url + "\">" + description + "</a>";
  }
}

The URL validation test is done using a regular expression and a Java Pattern object. Using the Whitebox class will ensure that the pattern object is configured correctly and that our AnchorTag is in the correct state. This demonstrated by the JUnit test below:

  /**
   * Works for private instance vars. Does not work for static vars.
   */
  @Test
  public void accessPrivateInstanceVarTest() throws Exception {

    Pattern result = Whitebox.<Pattern> getInternalState(instance, "pattern");

    logger.info("Broke encapsulation to get hold of state: " + result.pattern());
    assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());
  }

The crux of this test is the line:

    Pattern result = Whitebox.<Pattern> getInternalState(instance, "pattern");

...which uses reflection to return the Pattern object private instance variable. Once we have access to this object, we simply ask it if it has been initialised correctly be calling:

    assertEquals("^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", result.pattern());

In conclusion I would suggest that using PowerMock to explicitly test an object’s internal state should be used only when you can’t use straight forward classic JUnit test for behavioural testing. Having said that, it is another tool in your toolbox that’ll help you to write better code.

 

From http://www.captaindebug.com/2011/10/testing-objects-internal-state-with.html

Object (computer science) unit test

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Spring Boot, Quarkus, or Micronaut?
  • Full Lifecycle API Management Is Dead
  • Introduction to Containerization
  • mTLS Everywere

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: