M Sach
M Sach

Reputation: 34424

Java How to mock the object and static method in java?

I am writing a junit of CustomerHelper which internally calls the method of AccountHelper object. The CustomerHelper is creating the AccountHelper object with new operator inside one of its method. Now if i want to mock the AccountHelper object.Is there any way i can do it?

If this dependency (AccountHelper in this case) would have been injected by some setter or constructor, i could have set my MockAccountHelper.Right? But is there any way we can do mocking when we are creating dependency with New operator?

Second question:- Is there anyway we can mock static methods using core java library without going for Power/Easy Mock?Even if i go power mocks , want to understand how it is doing it internally in brief?

Upvotes: 1

Views: 1916

Answers (5)

Nikhil Jadhav
Nikhil Jadhav

Reputation: 11

I use the following code structure when testing static methods.

Powermock.mockStatic(Something.class)

Something.someMethod(); // Static Method you want to mock
EasyMock.expectLastCall().andReturn(/*Whatever you want to return*/);

Powermock.replay(Something.class);

// Call which makes use of Something.someMethod

Powermock.verify(Something.class);

Ideally you shouldn't need to test static methods. PowerMock is a Java framework that allows you to unit test code normally regarded as untestable.

Upvotes: 0

There is powermockito library available to mock the static method call inside a testing class. The maven repository for powermockito library is:

<dependency>
 <groupId>org.powermock</groupId>
 <artifactId>powermock-api-mockito</artifactId>
 <version>1.6.6</version>
</dependency>

If you want to need more about powermockito, here is a link.

Upvotes: 0

Bhaskar
Bhaskar

Reputation: 7523

If this dependency (AccountHelper in this case) would have been injected by some setter or constructor, i could have set my MockAccountHelper.Right? But is there any way we can do mocking when we are creating dependency with New operator?

Yes - thats right, but more important that having the object injected is to have the type of object implement an interface which can then be used by mocking type too. The problem with mocking types that dont have any clear interface is that it is not easy to create parallel mocking types that are guarenteed to honor the original contract, while varying the implementation.

The only way I see possible in your case is to create a new type AccountHelperMock that extends AccountHelper and overrides all methods ( I hope it can ). Then in your code have the new AccountHelper() replaced by new AccountHelperMock() manually where you want to mock this.

Upvotes: 0

jumping-jack
jumping-jack

Reputation: 237

You will need a way to set the desired mock of AccountHelper to your CustomerHelper in your test cases. So your CustomerHelper class will require either a setter for AccountHelper or a constructor that can pass the desired AccountHelper. I guess there is no way for you to set a mock, if AccountHelper is instantiated locally in a method. You don't have access to it from outside(like your junit testcase), it's scope is just local to your method.

You cannot mock static methods. I guess that mocking libraries create mocks dynamically using some bytecode generation libraries such as http://asm.ow2.org/index.html or http://cglib.sourceforge.net/ The bytecode framework will generate the mock classes bytecode at runtime. And they do it by overriding methods. But static methods cannot be overridden.

Tiberiu

Upvotes: 0

Cameron Skinner
Cameron Skinner

Reputation: 54286

JMockit allows you to easily mock static methods and internally-constructed objects.

You'd do something like this:

@Test
public void testWhatever() {
    new Expectations() {
        AccountHelper accountHelper;
        {
            new AccountHelper();
            accountHelper.someMethod();
    }}
    objectUnderTest.doWhatever();
}

I don't believe there is a built-in way to mock static methods in the core Java library. I'm also not sure exactly what happens internally, but I think that JMockit does some kind of bytecode-level tinkering to replace classes on the fly.

Upvotes: 1

Related Questions