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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

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
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

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Why I Started Using Dependency Injection in Python
  • Dropwizard vs. Micronaut: Unpacking the Best Framework for Microservices
  • Understanding the Dependency Injection Lifecycle: Singleton, Scoped, and Transient With Detailed Examples
  • Dependency Injection

Trending

  • Dropwizard vs. Micronaut: Unpacking the Best Framework for Microservices
  • Performing and Managing Incremental Backups Using pg_basebackup in PostgreSQL 17
  • Creating a Web Project: Caching for Performance Optimization
  • Cosmos DB Disaster Recovery: Multi-Region Write Pitfalls and How to Evade Them
  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Using PowerMock to Mock Constructors

Using PowerMock to Mock Constructors

By 
Roger Hughes user avatar
Roger Hughes
·
Oct. 20, 11 · Interview
Likes (2)
Comment
Save
Tweet
Share
73.4K Views

Join the DZone community and get the full member experience.

Join For Free

In my opinion, one of the main benefits of dependency injection is that you can inject mock and/or stub objects into your code in order to improve testability, increase test coverage and write better and more meaningful tests. There are those times, however, when you come across some legacy code that doesn’t use dependency injection and held together by composition rather than aggregation.

When this happens, you have three options:

  1. Ignore the problem and not write any tests.
  2. Refactor like mad, changing everything to use dependency injection.
  3. Use PowerMock to mock constructors

Obviously, option 1 isn’t a serious option, and although I’d recommend refactoring to move everything over to dependency injection, that takes time and you have to be pragmatic. That’s where PowerMock comes in... this blog demonstrates how to use PowerMock to mock a constructor, which means that when your code calls new it doesn’t create a real object, it creates a mock object.

To demonstrate this idea, the first thing we need is some classes to test, which are shown below.
public class AnyOldClass {

  public String someMethod() {
    return "someMethod";
  }
}
public class UsesNewToInstantiateClass {

  public String createThing() {

    AnyOldClass myclass = new AnyOldClass();

    String returnValue = myclass.someMethod();
    return returnValue;
  }
}

The first class, AnyOldClass, is the class that the code instantiates by calling new. In this example, as the name suggests, it can be anything.

The second class, the aptly named UsesNewToInstantiateClass, has one method, createThing(), which when called does a:

    AnyOldClass myclass = new AnyOldClass();

This is all pretty straight forward, so we’ll move quickly on to the PowerMock assisted JUnit test:

import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.expectNew;
import static org.powermock.api.easymock.PowerMock.replay;
import static org.powermock.api.easymock.PowerMock.verify;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.annotation.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(UsesNewToInstantiateClass.class)
public class MockConstructorTest {

  @Mock
  private AnyOldClass anyClass;

  private UsesNewToInstantiateClass instance;

  @Test
  public final void testMockConstructor() throws Exception {

    instance = new UsesNewToInstantiateClass();

    expectNew(AnyOldClass.class).andReturn(anyClass);

    final String expected = "MY_OTHER_RESULT";
    expect(anyClass.someMethod()).andReturn(expected);

    replay(AnyOldClass.class, anyClass);
    String result = instance.createThing();
    verify(AnyOldClass.class, anyClass);
    assertEquals(expected, result);
  }

}

Firstly, this class has the usual PowerMock additions of:
@RunWith(PowerMockRunner.class)
@PrepareForTest(UsesNewToInstantiateClass.class)

at the top of the file plus the creation of the anyOldClass mock object. The important line of code to consider is:

    expectNew(AnyOldClass.class).andReturn(anyClass);

This line of code tells PowerMock to expect a call to new AnyOldClass() and return our anyClass mock object.

Also of interest are the calls to replay and verify. In the example above, they both have two arguments. The first, AnyOldClass.class relates to the expectNew(...) call above, whilst the second, anyClass refers to the straight forward mock call expect(anyClass.someMethod()).andReturn(expected);.

There are those times when you should really let new do what it does: create a new object of the requested type. There is a body of opinion that says you can over-isolate your code when testing and that mocking everything reduces the meaning and value of a test. To me there’s no right answer to this and it’s a matter of choice. It’s fairly obvious that if your code accesses an external resource such as a database, then you’d either refactor and implement DI or use PowerMock. If your code under test doesn’t access any external resources, then it’s more of a judgement call on how much code isolation is too much? This perhaps needs some thought and may be the subject for another blog on anther day...

 

From http://www.captaindebug.com/2011/10/using-powermock-to-mock-constructors.html

Dependency injection

Opinions expressed by DZone contributors are their own.

Related

  • Why I Started Using Dependency Injection in Python
  • Dropwizard vs. Micronaut: Unpacking the Best Framework for Microservices
  • Understanding the Dependency Injection Lifecycle: Singleton, Scoped, and Transient With Detailed Examples
  • Dependency Injection

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!