Junit test case with Mockito - junit

I am creating junit test cases for my project. I have the below code, where I would like to create a mock,
String propertyFilePath = System.getProperty("path.to.properties");
Resource propertyFile = new FileSystemResourceLoader().getResource(propertyFilePath);
Properties properties = PropertiesLoaderUtils.loadProperties(propertyFile);
I am using junit and mockito-core jar. I tried with below code,
System.setProperty("path.to.properties", "dummyPathToProperties"); //invalid Path
Properties properties = mock(Properties.class);
Resource propertyFile = new FileSystemResourceLoader().getResource("dummyPathToProperties");
when(PropertiesLoaderUtils.loadProperties(propertyFile)).thenReturn(properties);
With above code it throws error when mocking loadProperties method. How can I mock a spring static class and return my mock properties object ?
Any help will be really appreciated.

Mocking static methods requires you to go down the full nine yards and make use of PowerMock. The exact steps to mock static methods are outlined in their documentation for example.
In essence:
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest(ClassThatContainsStaticMethod.class) annotation at the class-level of the test case.
Use PowerMock.mockStatic(ClassThatContainsStaticMethod.class) to mock all methods of this class.
Use PowerMock.replay(ClassThatContainsStaticMethod.class) to change the class to replay mode.
Use PowerMock.verify(ClassThatContainsStaticMethod.class) to change the class to verify mode.
But of course: consider not using PowerMock; by changing your code so that you don't have to mock the static call. But of course, it is kinda weird to add a wrapper around such a framework-provided static method.

Related

How do you bypass static method calls?

I have this line which is interferring in a unit test:
OtherClass.staticMethodThatWillErrorIfCalled().isAvailable();
If it wasn't static I could just mock OtherClass and then do this:
Mockito.doReturn(null).when(mockedOtherClass).staticMethodThatWillErrorIfCalled();
Mockito.doReturn(true).when(mockedOtherClass).isGuiMode();
and the fact that it will error if called makes my attempts at using powermockito futile.
I'm not sure how I can do this. All I want to do is skip over this line (it's an if check) and continue on as if it had returned true. What is the best way to do this?
I would require more info to give a more specific answer but this is what I am thinking...
First tell PowerMockito that you will be mocking a static method in OtherClass.
#RunWith(PowerMockRunner.class)
#PrepareForTest(OtherClass.class)
These are class level annotations that go on your unit testing class.
Then mock what to do when that method is called.
PowerMockito.mockStatic(OtherClass.class);
Mockito.when(OtherClass.isAvailable()).thenReturn(Boolean.TRUE);
Do this in your #Before method on your unit testing.

Guice injection leaking into other tests

I use Guice to instantiate a VocabularyAPI object for one of my unit tests unitTest1(). However, for another test (unitTest2()), I simply use mockito's #Mock annotation to mock an instance of the same class - VocabularyAPI.
I noticed that when I only run unitTest2() - mockito's mock setting for my VocabularyAPI is configured correctly. However, when I run the entire test suite (both unitTest1() and unitTest2()), both the tests are instantiated with the settings from the injector.
How can I limit the scope of the injected object to only inside the test that it is being injected? I want to be able to use the injected object in unitTest1() and mocked object for unitTest2().
Any problems in using local variables?
In unitTest1():
VocabularyAPI vocabularyAPI = // inject (I'm not familiar with Guice)
In unitTest2():
VocabularyAPI vocabularyAPI = Mockito.mock(VocabularyAPI.class);

Schedule Expression

I am trying to create a Junit test for a method which includes ScheduleExpression. I have tried to use PowerMockito to mock it but I continue to get a error message which reads
java.lang.ClassFormatError: Absent Code attribute in method
that is not native or abstract in class file javax/ejb/ScheduleExpression
Here is how I am using PowerMockito
ScheduleExpression expression = PowerMockito.mock(ScheduleExpression.class);
I have tried the annotations
#RunWith(PowerMockRunner.class)
#PrepareForTest(Static.class)
but they didn't work.
I have also tried Mockito version 1.9.5 but I get the same error. Am I missing a pom dependency?
Is there a way to Mock the ScheduleExpression?
You have to use the name of the class you want PowerMock to prepare for...
#PrepareForTest(ScheduleExpression.class)
However, in your case I don't see the need to use PowerMock because ScheduleExpression is not final, or has private or static methods you may be trying to mock.
Try just using vanilla Mockito instead of PowerMockito like this...
#RunWith(MockitoJUnitRunner.class)
...
ScheduleExpression expression = Mockito.mock(ScheduleExpression.class);

Mocking #UriInfo using EasyMock or PowerMock

I have a REST service class in which uriInfo object is automatically injected through #UriInfo annotation. Now, while writing JUnit for this class, I want to get a mock object created for this UriInfo object without introducing any new setter methods into the tested class just for the sake of setting the mocked UriInfo into it. Kindly let me know if you have any suggestions. We are using EasyMock and PowerMock.
You can use Powermock's Whitebox to modify the internal state of an object. One of the simplest invocations is:
Whitebox.setInternalState(tested, myMock);

Class loading collision between Robolectric and Powermock

I'm trying to write a test that needs both Robolectric 2.2 and PowerMock, as the code under test depends on some Android libraries and third party libraries with final classes that I need to mock.
Given that I'm forced to use the Robolectric test runner through:
#RunWith(RobolectricTestRunner.class)
...I cannot use the PowerMock test runner, so I'm trying to go with the PowerMock java agent alternative, without luck so far.
I have setup everything according to this guide but I'm facing a collision problem between classes required by the javaagent library and by robolectric through its dependency with asm-1.4. Both depend on
org.objectweb.asm.ClassVisitor
, but javaagent-1.5.1 ships with its own version where ClassVisitor is an interface while asm-1.4 version for the same namespace is an abstract class, with the corresponding error at runtime:
java.lang.IncompatibleClassChangeError: class org.objectweb.asm.tree.ClassNode has interface org.objectweb.asm.ClassVisitor as super class
I have even tried to modify the javaagent library jar to entirely remove the org.objectew.asm classes in there, but that doesn't work as ClassNotFoundException happens afterwards due to some other classes needed in the org.objectweb.asm package that only ship in the javaagent library jar, and not in the asm one.
Any ideas? According to examples out there the agent seems to work fine with, at least, the Spring test runner.
I had the same problem and while I didn't solve this problem as such, I wanted to share my approach, which removes the need for PowerMock (which is always a good thing in my view): I wanted to mock a call to
Fragment fooFragment = new FooFragment();
So what I did was addanother level of indirection. I created a FragmentProvider class:
public FragmentFactory fragmentFactory = new FragmentFactory();
[...]
Fragment fooFragment = fragmentFactory.getFooFragment();
After i did this, I could just mock out the factory with standard Mockito, like this:
FragmentFactory mockFactory = mock(FragmentFactory.class);
activity.fragmentFactory = mockFactory;
when(mockFactory.getFooFragment()).thenReturn(mockFooFragment);