I've been trying to use Mockito and PowerMockito to test my code. I have something akin to the following class:
public class asdfClass{
public static String methodToMock(String item, String otheritem){
return "asdf";
}
public static String methodToMock(String item){
return "asdf";
}
}
For whatever reason, though, running the following:
PowerMockito.spy(asdfClass.class);
PowerMockito.when(asdfClass.methodToMock(Mockito.any())).thenReturn("asdfghj");
appears to compile correctly but running
PowerMockito.spy(asdfClass.class);
PowerMockito.when(asdfClass.methodToMock(Mockito.any(), Mockito.any())).thenReturn("asdfghj");
does not and spits out a "'void' type not allowed here" error on the Mockito.any()s.
Does anyone know what to do about this? The only other result I saw on stackoverflow suggested that the reader take a look at the documentation, though I don't think it said anything about multiple arguments in a private static method.
(In the end I'm hoping to mock a void result with a doNothing though I've boiled the issue I'm having down to the fact that all of my void methods take multiple arguments)
EDIT: Never mind, got it: Is it possible to use partial mocking for private static methods in PowerMock? (Comment 4 on the chosen answer). Curiously this didn't work before but that might've been a typo on my part for all I know)
As per Is it possible to use partial mocking for private static methods in PowerMock?, PowerMockito.doReturn(mockData).when(DataProvider.class, "readFile", param1, param2, ...) does the trick.
You mock void methods, so it can't return anything, so the thenReturn() statement should be omitted (for example instead of when(), use doNothing()).
Related
I have class TaskType. It has method
public Class<? extends TaskParameters> getTypeParameters() {
return typeParameters;
}
next i want to mock this class and mock this method:
final TaskType TEST_PARAMETERS = Mockito.mock(TaskType.class);
when(TEST_PARAMETERS.getTypeParameters()).thenReturn(ScheduledParameters.class);
Mockito.doReturn(4).when(TEST_PARAMETERS).ordinal();
but i got problem:
error: no suitable method found for thenReturn(java.lang.Class<com.ucp.shard.bulkops.service.executor.ScheduleExecutorTest.ScheduledParameters>)
when(TEST_PARAMETERS.getTypeParameters()).thenReturn(ScheduledParameters.class);
Help, how can i mock this method?
Your question is missing a lot of information, it would be nice if you could update it. For example, you could share the code for TaskType.
First of all, it seems that TaskType is an enum as you are trying to call ordinal(), right? If it's the case, you need to remember that enums are final and cannot be mocked by Mockito by default (please read here for more information). If it's not an enum you can ignore it. :)
Regarding the problem mocking getTypeParameters(), you cannot do it directly due to type erasure (more information here). However, you can solve it using Mockito Answer:
final TaskType TEST_PARAMETERS = Mockito.mock(TaskType.class);
final Answer<Class<ScheduledParameters>> answer = invocation -> ScheduledParameters.class;
when(TEST_PARAMETERS.getTypeParameters())
.thenAnswer(answer);
Mockito.doReturn(4).when(TEST_PARAMETERS).ordinal();
I'm developing a function that uses reflection on a Class<?> object that is passed as parameter and returns a POJO with some fields populated, something like this:
public MyPojo functionDeveloper(Class<?> targetClass) { /*...*/ }
This function works fine and does what it needs to do, so no problems on this side.
Now, I need to create a unit test for this function, but I can't really figure out how to proceed here: We are supposed to mock as much as we can (which basically rules out creating a dummy parameter), with some random parameter from a generic class I would go like this:
#Tested
TestedClass testedClassInstance;
#Mocked
private MyGenericClass myGenericClass;
#Mocked
private Field[] fields;
#Test
public void testFunction() {
new Expectations(testedClassInstance) {
myGenericClass.getDeclaredFields();
result = fields;
}
/* assertions here*/
}
...and my intention with the Class<?> parameter was the same: being able to tell "when the code says "targetClass.getDeclaredFields()", then return the mocked object "field" I declared before, but jMockIt is complaining about not being able to mock the Class<?> object.
So, how do I proceed here? I get that java.lang.Class is "special" and all that, and there's probably something I'm missing from how jMockIt works. Any idea?
When you use Mocked on a class, you holds a mocked instance automatically created by jmockit lib.
So, try myGenericClass.getClass().getDeclaredFields()
More details : https://jmockit.github.io/tutorial/Mocking.html#mocked
You have a really simple case of a function. Functions are incredibly easy to test and rarely need mocks. They receive some input and return some output. What you need to do, is to test that some input produced some output.
#Tested
TestedClass testedClassInstance;
#Test
public void egReturnsAllFieldsOfTheProvidedClass() {
MyPojo result = testedClassInstance.functionDeveloper(MyGenericClass.class)
/* assertions here*/
}
I have a class Foo with private and public or protected methods. For example:
public class Foo{
private int number;
public Foo(){
setup();
doSthing();
}
private void doSthing(){
number=10;
}
public void setup(){
}
protected int getNumber(){
return number;
}
public void run(){
getNumber();
//Do blah blah...
}
}
And I am trying to test this class using Mockito.
public class FooTest
{
public void testMethods()
{
Foo foo = PowerMockito.mock (Foo.class);
//1 What should I do to see that setup() and doSthing()
//has been called on Foo construction
mock.run();
//2 What should I do to see that getNumber()
//has been called on run() method call
}
}
I am also hoping to include "times(1)" if possible. I'd appreciate your help.
You are getting this wrong:
First of all: please do not use any of the PowerMock... frameworks. They rely on byte code manipulation; and sooner or later that calls for trouble. Believe me, I have spent many hours hunting really strange errors for no good reasons.
Then: do not test your code this way!
You use a mocking framework to create/control those objects that you pass to your "class under test". You don't use the framework to directly test your "class under test"!
You also don't want to write test code that knows about private methods - those are implementation details.
What you do instead:
a) as said, you can use mocking to pass objects into your class under test. And then you can control/verify those mocks see the calls that you expect your "class under test" to make
b) you create objects of your "class under test" ... and then "assert" on the properties of those objects; or on results that method calls return.
Just to be precise: a mocked object ... doesn't know anything about the code in the "original" class. It is a mock! You can't use it for the kind of testing that your question implies you want to do. Either you call methods on your real class; or you specify something for a mock. But creating a mock to then "associate" it to the concrete class implementation ... is simply impossible.
Finally: if you think that your concrete class is actually "too big" to just be created the normal way for tests ... then chances are: your class is simply too big for anything else. Classes should be small; and their design should follow SOLID principles.
Long story short: don't try to force un-testable code into "tests", by using PowerMock... You better invest some more time to improve the quality of your production code; that will result in much higher "return on investment".
My intent is to do unit test of private methods and I understand on how to import the #VisibleForTesting and use it for a private method. I have done a quite a bit of search but unable to see a complete example that demonstrates this feature.
For eg:
class MyClass {
#VisibleForTesting
private double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Now in JUnit, I must be able to do
#Test
public void testProvateMethod() {
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
}
But the difficult part is I am unable to comprehend/do the following
a) Snippet of maven compiler plugin for including the relevant annotation processor
b) Actually be able to test a private method. (since it throws error related to visibility of method)
I am unable to do it in action while I write a test in JUnit (due to the private access error). For eg: mvn clean test
Please provide a complete example to really all steps involved in getting the JUnit test of private methods done.
Firstly, I do not recommend to test private methods, unit tests should test public methods in most cases. If you have to test private methods, it usually indicates a bad design.
Regarding to #VisibleForTesting , it is used in package-methods in Guava, and not part of JUnit API. The annotation is just a tag to indicate the method can be tested, it even doesn't be loaded in JVM. So if you need to test non-public methods, make the methods package scope which is visible to unit test classes in same package.
Last, by using reflect can access private methods, if you really have to test them.
Testing a private method must be one of the bad patterns.
However, there are times when you often feel the urge to test private methods.
In this case, I personally use ReflectionTestUtils to test the method. This is because we wanted to keep the original intent of the private method, and only test the method. Below is an example of my sample.
MyClass myClass = new MyClass();
ReflectionTestUtils.invokeMethod(myClass, "getWorkArray", values, length);
One drawback is the fact that I get the name of the method as a String and it is quite a bit sad except for the fact that refactoring does not convert correctly in IDEA.
I hope it helps.
Thanks.
You can remove private keyword:
class MyClass{
#VisibleForTesting double[] getWorkArray(double[] values,int length) {
:
:
return <some double array>
}
}
Then you are able to:
MyClass object = new MyClass();
assertNotNull(object.getWorkArray(...);
in your test.
I've developed an application in Java and I'm trying to create unit tests using Powermockito (I should add that I'm new to unit testing).
I have a class called Resource which has a static method called readResources:
public static void readResources(ResourcesElement resourcesElement);
ResourcesElement is also coded by me.
In testing, I want to create my own Resource, so I want the above method to do nothing.
I tried using this code:
PowerMockito.spy(Resource.class);
PowerMockito.doNothing().when(Resource.class, "readResources", Matchers.any(ResourcesElement.class));
The unit test throws an exception:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36)
Powermockito also suggest that I should use thenReturn or thenThrow after when, but it seems that the method 'when' returns void when it is called after doNothing (which is logical).
If I try:
PowerMockito.when(Resource.class, "readResources", Matchers.any(ResourcesElement.class)).....
doNothing is not an option after when.
I managed to make methods without arguments to do nothing, using the 2 arguments version of the method. For example:
PowerMockito.doNothing().when(Moduler.class, "startProcessing");
This works (startProcessing doesn't take any arguments).
But how can I make methods that do take arguments to do nothing with Powermockito?
You can find a fully functional example below. Since you didn't post the complete example, I can only assume that you did not annotate the test class with #RunWith or #PrepareForTest because the rest seems fine.
#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!");
}
}
Why go through so much trouble just so that your method does not do anything. Just calling PowerMockito.mockStatic(Resource.class) should replace all static methods in your class with default stubs which basically mean they do nothing.
Unless you do want to change the behavior of your method to actually do something just calling PowerMockito.mockStatic(Resource.class) should suffice. Ofcourse this also means all static methods in the class are stubbed which you need to consider.
If doNothing() isn't working you can hack it a bit using the PowerMockito.doAnswer(). This lets you mock into void methods that are supposed to do something, like setting values, etc. If doNothing() doesn't work, using a blank doAnswer() should work fine.
Example:
PowerMockito.doAnswer(new org.mockito.stubbing.Answer<Object>() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return null; //does nothing
}
}).when(mockObject).methodYouWantToDoNothing(args);
Maybe i can't undestand your question, but i believe it's necessary specify what must do
the method, so if you don't specify thenReturn or thenThrow or whatever powerMockito doesn't know what have to do when read your real code, for example:
REAL CODE:
IPager pag;
IPagerData<List<IDeute>> dpag;
pag = new PagerImpl();
pag.setFiles(nombrefilesPaginador);
pag.setInici(1);
dpag = gptService.obtenirDeutes(idSubjecte, idEns, tipusDeute, periode, pag);
Testing real code by mockito:
IPager pag = new PagerImpl();
pag.setInici(1);
pag.setFiles(0);
when(serveiGpt.obtenirDeutes(eq(331225L),
eq(IConstantsIdentificadors.ID_ENS_BASE),
Matchers.any(ETipusDeute.class),
Matchers.any(EPeriodeDeute.class),
eq(pag)))
.thenThrow(new NullPointerException(" Null!"));
If haven't specify the return my test will be fail.
I hope it helps.
I tried doNothing with different variations but nothing worked except the below solution.
#Before
public void setUp(){
obj = new ClassObj (parameters);
//parameters should also include the class obj for which void method is available
}