This code mocks a static void method in a class and overrides its behavior. (Taken from this question here)
#RunWith(PowerMockRunner.class)
#PrepareForTest({Resource.class})
public class MockingTest{
#Test
public void shouldMockVoidStaticMethod() throws Exception {
PowerMockito.spy(Resource.class);
PowerMockito.doNothing().when(Resource.class, "readResources", Mockito.any(String.class));
//no exception heeeeere!
Resource.readResources("whatever");
PowerMockito.verifyStatic();
Resource.readResources("whatever");
}
}
class Resource {
public static void readResources(String someArgument) {
throw new UnsupportedOperationException("meh!");
}
public static void read(String someArgument) {
throw new UnsupportedOperationException("meh!");
}
}
How can I intercept all method calls instead of individually specifying the methods?
It tried PowerMockito.doNothing().when(Resource.class) and PowerMockito.doNothing().when(Resource.class, Matchers.anything()) but these do not work.
This:
PowerMockito.doNothing().when(Resource.class, Matchers.anything())
Doesn't work because Matchers.anything() creates a matcher for Object and the above when() is trying to find methods based on the type. Try passing instead Matchers.any(String.class). This will only work for static methods with the same parameter lists. Not sure if there's a way to make a more generic override.
If you want to mock ALL static methods of a class, I think you can use PowerMockito.mockStatic(..) instead of PowerMockito.spy(..):
#Test
public void shouldMockVoidStaticMethod() throws Exception {
PowerMockito.mockStatic(Resource.class);
//no exception heeeeere!
Resource.readResources("whatever");
PowerMockito.verifyStatic();
Resource.readResources("whatever");
}
Hope it helps you.
Related
I have a private method whose invocation I want to test without caring about the arguments. I want to test if it was called at all or not.
MyClass.java
public void doStuff(){
unload(args);
}
private void unload(List<String> args) {
//
}
So I used following:
MyClasstest.java
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
verifyPrivate(myClass, times(1)).invoke("unload",any(List.class));
// verifyPrivate(myClass, times(1)).invoke("unload",any()); //same result with this
This test fails with following exception:
Wanted but not invoked com.MyClass.unload(
null );
However, there were other interactions with this mock .......
(actual values with which it was called)
Can verifyPrivate be called with only actual arguments & not with any()?
Here is a working example of what you are trying to do:
You might just missing the #PrepareForTest annotation, which has to point to the correct class. If your class is an external one use #PrepareForTest(MyClass.class), the example below shows it with an internal class.
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClassTest.class)
public class MyClassTest {
static class MyClass {
public void doStuff(){
unload(null);
}
private void unload(List<String> args) {
}
}
#Test
public void test() throws Exception {
MyClass myClass = PowerMockito.spy(new MyClass());
myClass.doStuff();
PowerMockito.verifyPrivate(myClass, Mockito.times(1)).invoke("unload", Mockito.any());
}
}
Note that you should consider whether you really want to do this in a UnitTest. Normally your UnitTest should not be concerned about whether a private method is used or not, it should be focused on verifying that the correct result is returned or the correct object state is reached.
By adding knowledge about the internal behaviour of the class into it, you test is tightly coupled to the implementation which might not be a good thing.
I have below class
class PowerMockitoTest{
private void TestPrivateMethod(){
System.out.println("Inside private method");
}
public void TestPublicMethod(){
System.out.println("Inside public method");
TestPrivateMethod();
}
}
I have created Test class as below
#RunWith(PowerMockRunner.class)
public class PowerMockitoExampleTest {
#Test
public void test() throws Exception {
PowerMockitoTest testclass = PowerMockito.spy(new PowerMockitoTest());
PowerMockito.doNothing().when(testclass,"TestPrivateMethod");
testclass.TestPublicMethod();
}
}
Instead of getting OP as 'Inside public method' I am getting very strange OP as 'Inside private method'. Though i have stubbed private method to do nothing its getting called as well as sysout for public method is not getting printed.
Its working fine when i used PowerMockito.doAnswer() but it requires method to be at package level instead of private.
Write it this way:
PowerMockitoTest testclass = PowerMockito.spy(new PowerMockitoTest());
try {
PowerMockito.doNothing().when(testclass, PowerMockito.method(PowerMockitoTest.class, "TestPrivateMethod")).withNoArguments();
} catch (Exception e) {
e.printStackTrace();
}
testclass.TestPublicMethod();
btw:
Testing is about mocking input and investigating outputs (it can be state of module, result of function or calls to another functions).
You should not mock private methods, as their result should not be treated as an input becouse they are not visible from outside.
The missing part in your code i believe is the #PrepareForTest part. You have to add class name with #PrepareForTest after #RunWith annotation
#RunWith(PowerMockRunner.class)
#PrepareForTest({Class1.class, Class2.class})
public class ClassTest
I'm trying to mock private static method anotherMethod(). See code below
public class Util {
public static String method(){
return anotherMethod();
}
private static String anotherMethod() {
throw new RuntimeException(); // logic was replaced with exception.
}
}
Here is me test code
#PrepareForTest(Util.class)
public class UtilTest extends PowerMockTestCase {
#Test
public void should_prevent_invoking_of_private_method_but_return_result_of_it() throws Exception {
PowerMockito.mockStatic(Util.class);
PowerMockito.when(Util.class, "anotherMethod").thenReturn("abc");
String retrieved = Util.method();
assertNotNull(retrieved);
assertEquals(retrieved, "abc");
}
}
But every tile I run it I get this exception
java.lang.AssertionError: expected object to not be null
I suppose that I'm doing something wrong with mocking stuff. Any ideas how can I fix it?
To to this, you can use PowerMockito.spy(...) and PowerMockito.doReturn(...).
Moreover, you have to specify the PowerMock runner at your test class, and prepare the class for testing, as follows:
#PrepareForTest(Util.class)
#RunWith(PowerMockRunner.class)
public class UtilTest {
#Test
public void testMethod() throws Exception {
PowerMockito.spy(Util.class);
PowerMockito.doReturn("abc").when(Util.class, "anotherMethod");
String retrieved = Util.method();
Assert.assertNotNull(retrieved);
Assert.assertEquals(retrieved, "abc");
}
}
Hope it helps you.
If anotherMethod() takes any argument as anotherMethod(parameter), the correct invocation of the method will be:
PowerMockito.doReturn("abc").when(Util.class, "anotherMethod", parameter);
I'm not sure what version of PowerMock you are using, but with the later version, you should be using #RunWith(PowerMockRunner.class)
#PrepareForTest(Util.class)
Saying this, I find using PowerMock to be really problematic and a sure sign of a poor design. If you have the time/opportunity to change the design, I would try and do that first.
According to the example in the Jmockit tutorial this code should do the trick:
#BeforeClass
public static void setUpClass() {
new MockUp<UtilJndi>(){
#Mock
public static String getDirectoryFromContext(Property jndiName) // line 66
throws DirectoryNotFoundException {
return "noDirectory";
}
};
}
But it shows:
myclass.java:[66,29] error: Illegal static declaration
How can I resolve this?
I will add another workaround wich works for me:
I create my mocked class extending MockUp:
public static class MockUtilJndi extends MockUp<UtilJndi> {
public MockUtilJndi() {
super();
}
#Mock
public static String getDirectoryFromContext(Property jndiName)
throws DirectoryNotFoundException {
return "noDirectory";
}
}
If you notice I call the super() inside my constructor. Cause according to documentation if you call MockUp constructor it will change the implementation in the target class.. so once you have this in your mocked class constructor you just need to create your class inside the #BeforeClass annotated method:
#BeforeClass
public static void setUpClass() {
new MockUtilJndi();
}
Ok, I will update my comment to an answer.
First, the error message is very clear. "Illegal static declaration" just means, that the static keyword is placed wrong. Remove it!
As you are trying to mock a static method, you might have believed that you must put the static keyword also. But the documentation for the Mock annotation says:
Method modifiers (including public, final, and even static), however, don't have to be the same.
That simply means, you can mock static methods even without declaring it static.
Hmm ... I strongly feel, that the documentation's wording is a bit confusing. Obviously, it is not an option, but you must not declare it static.
I have a Mainclass that I need to test which is dependent on other class.
Now I am creating a mock for that class
How to test void methods using easymock
MainClass{
mainClassMethod(){
dependencyClass.returnVoidMethod();
//other code
}
}
TestClass{
#Before
setUpMethod(){
DependencyClass dependencyClassMock = EasyMock.createMock(DependencyClass.class);
}
#Test
testMainClassMethod(){
EasyMock.expect(dependencyClassMock.returnVoidMethod()).andRetur //this is not working
dependencyClassMock.returnVoidMethod();
EasyMock.expectLastCall().anyTimes(); //If I use this, it is invoking the method.
}
}
//My dependency class code
DependencyClass implements ApplicationContextAware{
private static ApplicationContext applicationContext;
private static final String AUTHENTICATION_MANAGER = "authenticationManagers";
returnVoidMethod(){
ProviderManager pm = (ProviderManager) getApplicationContext().getBean(AUTHENTICATION_MANAGER); //this is returning null
}
//othercode
//getters and setters of application context
}
As described in the Easymock Documentation you don't put the method inside an expect() (since there is no return). You can just call the mocked method by itself and if it is in "record" mode then it is implied an expect.
dependencyClassMock.returnVoidMethod();
If you need to throw an Exception or say the method can be called anyTimes() you can use expectLastCall()
#Test
public void testMainClassMethod(){
dependencyClassMock.returnVoidMethod();
EasyMock.expectLastCall().anyTimes();
...
//later to replay the mock
EasyMock.replay(dependencyClassMock);
//now this method is actually called
dependencyClassMock.returnVoidMethod();
}
EDIT : Just noticed that you don't have the dependencyClassMock as field:
public class TestClass{
DependencyClass dependencyClassMock
#Before
setUpMethod(){
dependencyClassMock = EasyMock.createMock(DependencyClass.class);
}
...//rest of class is as described above
#dkatzel
the test is completely wrong..... you are calling manually a method and the you verify if it was called...of course it was! ...that's not the right way (my opinion)
A better way (my opinion) would be to extend the mehod class you would like to test, override that method and in the body just put a boolean variable as a flag to k now if the method was called or not....you don't even need to use EasyMock
Example
Class DependencyClass {
public void returnVoidMethod() {
[.... content ...]
}
}
Class A_test {
#Test
public void checkVoidMethodCalled() {
A_mod obj = new A_mod();
mainClassMethod();
assertTrue(obj.called);
}
Class A_mod extends DependencyClass {
boolean called = false;
#Override
public void returnVoidMethod() {
called = true;
}
}
}
You are welcome.