Good time!
I need to substitute the class' private void method with a mock implementation, and can't to figure out how to do this. I've tried to use such a construction:
Test test = PowerMock.createPartialMock(Test.class, "setId");
PowerMock.expectPrivate(test , "setId", EasyMock.anyLong()).andAnswer(
new IAnswer<Void>() {
#Override
public Void answer() throws Throwable {
return null;
}
});
PowerMock.replay(test);
but the internal PowerMock's class called WhiteBox invokes my "setId" method which is wrong for my task. Could someone, please, suggest, how to avoid the method invokation and possibly to replace the method body with a custom one?
Finally. I've got the solution.
The problem was I missed the following annotations:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Test.class)
Anyway, it seems rather confusing that to make the PowerMock working I need to add some annotations. If that wasn't a legacy code I'd prefer Mockito.
Not quite sure that I get the question.
But for me code below works perfect and just string "Invoked!" is getting printed
and if I remove test.setS(33L); test will fail with exception:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MainTest.Test2.class)
public class MainTest {
#Test
public void testName() throws Exception {
Test2 test = PowerMock.createPartialMock(Test2.class, "setS");
PowerMock.expectPrivate(test , "setS", EasyMock.anyLong()).andAnswer(
new IAnswer<Void>() {
#Override
public Void answer() throws Throwable {
System.out.println("Invoked!");
return null;
}
}).atLeastOnce();
PowerMock.replay(test);
test.setS(33L);
PowerMock.verify(test);
}
class Test2 {
long s;
private long getS() {
return s;
}
private void setS(long s) {
this.s = s;
System.out.println("Not this!");
}
}
}
Related
I am trying to write unit test cases for one of the methods in code.Below is the method
public boolean isValid() {
if(object == null)
return false
//do something here and return value.
}
The object is created by this method which is done before without getter setter method.
private Object returnObject() {
object = Axis2ConfigurationContextFactory.getConfigurationContext();
return object;
}
When I try to test isValid(), the object is always null, so it never goes in the code to do something.
I was checking if there is any way to skip that line or make the object not null. I also tried creating an object using returnObject method. But it uses Axis library classes which throws error if it does not find certain data. What can be done in this case? I am dealing with legacy code so any pointers would be helpful.
Edit : Adding test implementation.
#PowerMockIgnore({ "javax.xml.*", "org.w3c.dom.*", "javax.management.*" })
public class ClassTest {
private ClassTest classTestObj;
#BeforeMethod
public void callClassConstructor() {
classTestObj = //call class constructor
}
#BeforeClass
public void setUpClass() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public boolean isValidTest() {
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
As I mentioned in the before comment, you can make use of MockedStatic to mock the static method - https://javadoc.io/static/org.mockito/mockito-core/4.4.0/org/mockito/Mockito.html#static_mocks
So your code will somewhat look like the below one if you are making use of Mockito instead of PowerMockito.
#RunWith(MockitoJUnitRunner.class)
public class ClassTest
{
#Mock
private Object mockAxis2ConfigurationContextFactoryObject;
#Test
public boolean isValidTest() {
try (MockedStatic<Axis2ConfigurationContextFactory> mockedStatic = mockStatic(Axis2ConfigurationContextFactory.class)) {
mockedStatic.when(()->Axis2ConfigurationContextFactory.getConfigurationContext()).thenReturn(mockAxis2ConfigurationContextFactoryObject);
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
I am writing a test case for "headersection()" method. Inside this method, it is calling a constructor of another class, let's say "InformationHeader.java" class. Inside this constructor, it will invoke one method called as "makepage()". Again "makepage()" method will invoke another "createpage()" method.
I wanted to skip the method call to "createpage()" in my test case. Please suggest how to achieve this scenario?
private void headersection(Object child) {
headerobject = new InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4);
//lines of code
}
//InformationHeader.java
public InformationHeader(parameter_1, parameter_2, parameter_3, parameter_4) {
//lines of code
makepage();
//lines of code
}
public final void makepage() {
//lines of code
createpage(); //I wanted to skip this method call
}
Any help would be appreciated
Thanks
I hope I got your question, but as I mentioned in my comment, you could change the method a bit and create a method which could be mocked.
void headersection(Object child) {
headerobject = getInformationHeader(/*parameter*/)
//lines of code
}
InformationHeader getInformationHeader(/*parameter*/) {
return new InformationHeader(parameter_1,parameter_2,parameter_3,parameter_4);
}
I don't know your class name in which the headersection mehtod is stored, lets say SectionService. Now, you could use Mockito to create a so called spy
#InjectMock
SectionService serviceToTest;
SectionService spyServiceToTest = Mockito.spy(serviceToTest);
InformationHeader spyInformationHeader = Mockit.spy(new InformationHeader(/*parameter*/));
Now you can mock a call inside of the tested class:
Mockito.doReturn(spyInformationHeader).when(spyServiceToTest).getInformationHeader(//parameter);
Mockiot.doNothing().when(spyInformationHeader).createpage();
Here is a stackoverflow question which is dealing with spy calls and
here is the Mockito documentation.
I hope this helps, greetings Matthias
The answer using spies doesn't work. The new InformationHeader(/*parameter*/) will call createpage. You will have the same problem with EasyMock.
The problem is that you can't mock a method before creating a partial mock. So when the constructor is calling a method, it doesn't work.
I would probably rethink my design if I was you. But not having the full picture, I can't give advice on that.
Keeping the current design, the easiest is actually to do a manual mock. It goes like this.
public class MyTest extends EasyMockSupport {
#Test
public void test() {
InformationHeader header = new InformationHeader("a", "b", "c", "d") {
#Override
public void createpage() {
// do nothing
}
};
ToTest toTest = partialMockBuilder(ToTest.class)
.withConstructor()
.addMockedMethod("createHeader")
.mock();
expect(toTest.createHeader()).andReturn(header);
replayAll();
toTest.headersection(null);
}
}
class ToTest {
void headersection(Object child) {
InformationHeader headerobject = createHeader();
}
InformationHeader createHeader() {
return new InformationHeader("a", "b", "c", "d");
}
}
class InformationHeader {
public InformationHeader(String p1, String p2, String p3, String p4) {
makepage();
}
public final void makepage() {
createpage();
}
public void createpage() {
throw new RuntimeException("Should not be called");
}
}
I'll try to provide a hackneyed, useless example that reduces the problem nicely :-)
I have a GenericException, and a MoreSpecificException which extends GenericException.
I need to test that SomeService.doThis() throws a MoreSpecificException. JUnit lets me do this elegantly like so.
#Test(expected = MoreSpecificException.class)
public void testDoThis() throws GenericException {
new SomeService().doThis();
}
However, I also need to test that SomeService.doThat() throws a GenericException, so I tried this.
#Test(expected = GenericException.class)
public void testDoThat() throws GenericException {
new SomeService().doThat();
}
However, I found that if doThat() actually throws a MoreSpecificException then the second test still passes. I assume this is because MoreSpecificException is a GenericException and the annotation is implemented to respect that relationship.
While this is a sensible default behaviour, I don't want this. I want to test that doThat() throws a GenericException and only a GenericException. If it throws a MoreSpecificException or any other subclass of GenericException, I want the test to fail.
Reading the docs it doesn't seem I can do anything with the annotation to change this behaviour, so looks like I'll have to use another solution.
At the moment I'm resorting to the following ugly solution - EDIT made significantly less ugly by Nathan Hughes' answer :-)
#Test
public void testDoThat() {
try {
new SomeService().doThat();
Assert.fail();
} catch(GenericException ex) {
Assert.assertEquals(GenericException.class, ex.getClass());
}
}
Is there a more elegant way to achieve what I want within the JUnit framework?
BDD Style Solution
JUnit 4 + Catch Exception + AssertJ
The most elegant solution ;) Readable, without boilerplate code.
#Test
public void testDoThat() {
when(new SomeService()).doThat();
then(caughtException()).isExactlyInstanceOf(GenericException.class);
}
The code is identical for FEST Assertions 2 + Catch-Exceptions.
Source code
https://gist.github.com/mariuszs/7489706
Dependencies
org.assertj:assertj-core:1.4.0
com.googlecode.catch-exception:catch-exception:1.2.0
You can assert that the class of the Exception is what you expect:
#Test
public void testDoThat() {
try {
new SomeService().doThat();
Assert.fail();
} catch(GenericException ex) {
assertEquals(GenericException.class, ex.getClass());
}
}
Also got rid of the flag, instead having the test fail if no exception is thrown.
You can use the ExpectedException rule and a custom Hamcrest matcher that specifies which class can be thrown.
The following test will print that you expected an instance of RuntimeException, but got an IllegalArgumentException.
#Rule
public ExpectedException thrown = ExpectedException.none();
#Test
public void testThrows() {
thrown.expect(isClass(RuntimeException.class));
throw new IllegalArgumentException("FAKE");
}
public class ClassMatchMatcher extends BaseMatcher<Object> {
private final Class<?> expectedClass;
private ClassMatchMatcher(Class<?> expectedClass) {
this.expectedClass = expectedClass;
}
#Override
public boolean matches(Object item) {
return expectedClass.equals(item.getClass());
}
#Override
public void describeTo(Description description) {
description.appendText("an instance of ")
.appendText(expectedClass.getName());
}
}
public class ExtraMatchers {
public static Matcher<Object> isClass(Class<?> aClass) {
return new ClassMatchMatcher(aClass);
}
}
Edit: Added a static factory method to make the test code cleaner.
I need to test handleIn() method using Mockito.
However the code need to call this legacy code Util.getContextPDO which is a static method.
Note that in testing environment this Util.getContextPDO is always returns Exception, and I intend to bypass this Util.getContextPDO() by always return a dummy IPDO.
public class MyClass {
public IPDO getIPDO()
{
return Util.getContextPDO(); // note that Util.getContextPDO() is a static, not mockable.
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
// some important business logic.
return result;
}
}
Initially I thought this achieveable by using spy() of the class "MyClass", so I can mock the return value of getIPDO(). Below is my initial effort using spy ()
#Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
when(handler2.getIPDO()).thenReturn(pdo);
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
However the when(handler2.getIPDO()).thenReturn(pdo); is throwing the Exception that I want to avoid ( because handler2.getIPDO() ) seems to call the real method.
Any idea on how to test this part of code?
A good technique for getting rid of static calls on 3rd party API is hiding the static call behind an interface.
Let's say you make this interface :
interface IPDOFacade {
IPDO getContextPDO();
}
and have a default implementation that simply calls the static method on the 3rd party API :
class IPDOFacadeImpl implements IPDOFacade {
#Override
public IPDO getContextPDO() {
return Util.getContextPDO();
}
}
Then it is simply a matter of injecting a dependency on the interface into MyClass and using the interface, rather than the 3rd party API directly :
public class MyClass {
private final IPDOFacade ipdoFacade;
public MyClass(IPDOFacade ipdoFacade) {
this.ipdoFacade = ipdoFacade;
}
private IPDO getIPDO() {
return ipdoFacade.getContextPDO();
}
public String handleIn(Object input) throws Throwable
{
String result = "";
IPDO pdo = getIPDO();
someImportantBusinessLogic(pdo);
return result;
}
...
}
In your unit test, you can then easily mock your own interface, stub it any way you like and inject it into the unit under test.
This
avoids the need to make private methods package private.
makes your tests more readable by avoiding partial mocking.
applies inversion of control.
decouples your application from a specific 3rd party library.
Changed my testing to :
#Test
public void testHandleIn() throws Exception
{
IPDO pdo = new PDODummy();
MyClass handler = new MyClass ();
MyClass handler2 = spy(handler);
doReturn(pdo ).when( handler2 ).getIPDO();
PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
IPDO pdoNew = handler2.getIPDO();
Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
}
Solved after reading Effective Mockito.
when(handler2.getIPDO()).thenReturn(pdo);
Will actually call the method and then return pdo regardless.
Whereas:
doReturn(pdo).when(handler2).getIPDO();
Will return pdo without calling the getIPDO() method.
Is there any way that we can mock certain methods using existing objects ?
I used Power Mock to mock private methods but couldn't find out a way to do the above mentioned task.
Thanks
If I understand correctly, you need to stub out just a method of a real object. If that is the case and if you're using PowerMock with Mockito you can check out the 'Spy' feature. You can find an example here.
The simplest way to do it would be just override the method in the test case.
public class ClassToTest {
public int someMethod() {
return 1 + otherMethod();
}
protected int otherMethod() {
return 2;
}
}
public class ClassToTestTest {
#Test
public void testSomeMethod() {
ClassToTest classUnderTest = new ClassToTest() {
#Override
protected int otherMethod() {
return 3;
}
}
Assert.assertEquals(4, classUnderTest.someMethod());
}
}