How to mock An Interface Java PowerMockito - java

I m trying to mock an interface.
public interface FlowCopyParamsBusinessManager {
List<FlowCopyParams> findByAppli(String application, String sourcePattern)
throws FlowCopyParamsBusinessException;
}
In my code, when i call this method findByAppli, i would like to return a list of FlowCopyParams.
List<FlowCopyParams> lstFlowCopyParams = flowCopyParamsBusinessManager.findByAppli(
"TOTO","TATA);
Here my try in the class test:
#BeforeClass
public static void mockBeanIn() throws Exception {
List<FlowCopyParams> flowCopyParamsList = new ArrayList<>();
PowerMockito.spy(FlowCopyParamsBusinessManager.class);
PowerMockito.when(FlowCopyParamsBusinessManager.class, "findByAppli", Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
}
I have this error :
java.lang.IllegalArgumentException: object is not an instance of declaring class
I don't know why because the method findByAppli must have two string parameters, and i put Mockito.anyString() and i still have IllegalArgumentException.
Any clue ?
Thxs.

You don't need to use PowerMockito, and as its an Interface, theres no need to spy() as you are not relying on any non mocked logic.
It can be done like this, in your test class define a class variable.
private FlowCopyParamsBusinessManager flowCopyParamsBusinessManagerMock;
In an #Before annotated method:
flowCopyParamsBusinessManagerMock = Mockito.mock(FlowCopyParamsBusinessManager.class);
List<FlowCopyParams> flowCopyParamsList = new ArrayList<>();
when(flowCopyParamsBusinessManagerMock
.findByAppli(Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
Then refer to flowCopyParamsBusinessManagerMock in your tests.

My test did not work because I was trying to spy the class and not on the instance of FlowCopyParamsBusinessManager.class .
First , we have to create the mock :
FlowCopyParamsBusinessManager mockFlowCopyParamsBusinessManager = PowerMockito.mock(FlowCopyParamsBusinessManager.class);
Then , spy the instance :
PowerMockito.spy(mockFlowCopyParamsBusinessManager);
PowerMockito.when(mockFlowCopyParamsBusinessManager, "findByAppli", Mockito.anyString(), Mockito.anyString()).thenReturn(flowCopyParamsList);
It works as well !

I did this put this #RunWith(PowerMockRunner.class) at the top of the class. then mock Object with PowerMockito.mock(MyMock.class); This way use can mock a interface or final class.

Related

Mocking a local object inside a method of SUT using Mockito or PowerMocktio

I've class method like below which creates a local object and calls a method on that local object.
public class MyClass {
public someReturn myMethod(){
MyOtherClass otherClassObject = new MyOtherClass();
boolean retBool = otherClassObject.otherClassMethod();
if(retBool){
// do something
}
}
}
public class MyClassTest {
#Test
public testMyMethod(){
MyClass myClassObj = new MyClass();
myClassObj.myMethod();
// please get me here..
}
}
When I'm testing myMethod, I want to mock otherClassObject.otherClassMethod to return something of my choice. otherClassMethod does some class to Message Queues and I don't want that in Unit test. So I want to return true when I do otherClassObj.otherClassMethod(). I know I must have used a factory for MyOtherClass instantiation in this case but it's legacy code and I don't want to change any code now. I see that Mockito doesn't provide this facility to mock MyOtherClass in this case but possible with PowerMockito. However, I could not find an example for above scenario but found only for static class. How should I mock local object inside a method of SUT ?
I also referred to some other OS questions like - Mocking methods of local scope objects with Mockito but they were not helpful.
A code example will be of great help.
If you are using PowerMockito you can use the whenNew method
It should look something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class) //tells powerMock we will modify MyClass to intercept calls to new somewhere inside it
public class MyClassTest{
#Test
public void test(){
MyOtherClass myMock = createMock(MyOtherClass.class);
//this will intercept calls to "new MyOtherClass()" in MyClass
whenNew( MyOtherClass.class).withNoArguments().thenReturn( myMock) );
... rest of test goes here
}
Also this other SO post has example code too PowerMockito Mocking whenNew Not taking affect
OK, this is not a real answer but with PowerMockito you can do this:
final MyOtherClass myOtherClass = mock(MyOtherClass.class);
// mock the results of myOtherClass.otherClassMethod();
PowerMockito.whenNew(MyOtherClass.class).withNoArguments()
.thenReturn(myOtherClass);
// continue with your mock here
Now, not sure whether you actually need the result of this otherClassMethod here, but if you don't, I'd suggest you mock the results of myMethod() instead -- unless myMethod() is what you want to test because this other method has an influence on it, and yes, in this case a refactoring should be considered... And not delayed ad vitam aeternam...

Mocking helper class with Mockito

I have a plain helper class with public methods which I am using in the service level class. When I am writing test for the service class and trying to mock this helper class for one of the method it is going inside the methods and running every line. Since code inside this method is more complex I want to mock helper class with method(s) so that I don't have to take care of every detail inside helper class method.
Service Class
class HistoryServiceImpl implements CaseHistory {
#Override
public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
MemberUtil memberUtil = new MemberUtil();
List<CaseHistoryDto> caseHistoryDtoList = new ArrayList<CaseHistoryDto>();
List<CaseHistory> caseHistoryList = caseDetailDao.fetchCaseHistory(member.getId(), provider.getId());
for(CaseHistory caseHistory : caseHistoryList) {
CaseHistoryDto caseHistoryDto = new CaseHistoryDto();
caseHistoryDto.setMemberInfo(memberUtil.getMemberInfo(member, caseHistory.getCreateDate()));
caseHistoryDtoList.add(caseHistoryDto);
}
return caseHistoryDtoList;
}
}
Test Class
Class HistoryServiceTest {
#Mock MemberUtil memberUtil;
#InjectMocks private HistoryServiceImpl historyServiceImpl = new HistoryServiceImpl();
#Test
public void testGetCaseHistory() {
//why this line going inside real method and executing all lines?
when(memberUtil.getMemberInfo(any(Individual.class), any(Date.class))).thenReturn(member);
}
}
The reason that your test case is running all the lines in the "real" method, is because your mock object is never being used anywhere.
As written, you cannot mock MemberUtil in your HistoryServiceImpl, because you are manually instantiating it in the getCaseHistory() method. You need to make getCaseHistory() get its MemberUtil from somewhere else, so that you can inject your mock version in your test class.
The simplest solution would be to define your MemberUtil as a member variable, so that the #InjectMocks annotation can override the default value:
class HistoryServiceImpl implements CaseHistory {
MemberUtil memberUtil = new MemberUtil();
#Override
public List<CaseHistoryDto> getCaseHistory(Individual member, Individual provider) {
...
}
}
Alternately you could have HistoryServiceImpl accept an externally provided MemberUtil, either in its constructor or via a setter method. You can then easily pass in a mocked version in your test class.
Generally, utility classes are stateless, so another possible solution would be to convert MemberUtil to make all of its methods static. Then you can use something like PowerMock to mock your static methods.

Unit Testing Java Code - Mocking a non-static method of a different class

public class First {
public First(){
}
public String doSecond(){
Second second = new Second();
return second.doJob();
}
}
class Second {
public String doJob(){
return "Do Something";
}
}
Here I want to test the method "doSecond()" of class "First". For the same, I want to mock the method "doJob" of class "Second".
I know that I can create a mocked instance of class "Second" using the code below.
Second sec = mock(Second.class);
when(sec.doJob()).thenReturn("Stubbed Second");
But I cannot relate this mocked instance with class "First" as of the current code.
Without refactoring the source code, is there any way by which i can achieve the requirement.
Please help.
Take a look at powermock's ability to intercept calls to new and return mocks instead
https://code.google.com/p/powermock/wiki/MockConstructor
This doesn't require changing any sourcecode.
here's the test code where we actually return a mock when First.doSecond() calls new Second()
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class TestFirst {
#Test
public void mockSecond() throws Exception{
Second mock = PowerMockito.mock(Second.class);
PowerMockito.whenNew(Second.class).withNoArguments().thenReturn(mock);
PowerMockito.when(mock.doSecond()).thenReturn("from mock");
First first = new First();
assertEquals("from mock", first.doSecond());
}
}
It's tricky to mock an instance that you create inside of a method, but it's possible.
Using PowerMock, you can accomplish this with the PowerMock.expectNew() method:
#RunWith(PowerMockRunner.class)
#PrepareForTest(First.class)
public class StackOverflowTest {
#Test
public void testFirst() throws Exception {
Second secondMock = EasyMock.createMock(Second.class);
PowerMock.expectNew(Second.class).andReturn(secondMock);
expect(secondMock.doSecond()).andReturn("Mocked!!!");
PowerMock.replay(secondMock, Second.class);
String actual = new First().doSecond();
PowerMock.verify(secondMock, Second.class);
assertThat(actual, equalTo("Mocked!!!"));
}
}
Effectively, PowerMock is proxying the creation of the new object and substituting whatever value we want when we invoke doSecond().
So, it's possible. However, this is a terrible practice to get into.
One typically wants to mock objects if they involve an outside concern, such as another layer (i.e. database, validation), or if the desired output is coming from other objects that are injected but are safe enough to consider tested.
If your method is capable of getting or retrieving data from a non-injectable source, you should not want to mock that out.
Considering that your method is simple and straightforward, you should really not need to do any mocks here at all. But if you felt that you were forced to, you could do one of a few things:
Create a factory for the creation of Second, and mock the results of the returning factory object with Mockito.
Pass in an instance of Second to that method, and use Mockito as the mock instance.
Declare it as a field (i.e. injected dependency), and use Mockito.
For completeness, here is how the test can be written with the JMockit mocking API, without any refactoring of the original code under test:
public class ExampleTest
{
#Test
public void firstShouldCallSecond(#Mocked final Second secondMock) {
new NonStrictExpectations() {{
secondMock.doJob(); result = "Mocked!!!";
}};
String actual = new First().doSecond();
assertEquals("Mocked!!!", actual);
}
}

How to mock local variable obtained from another method of tested class?

I have following class
class MyClass{
public void m(InputStream is){
...
Parser eParser = getExcelFileParser();
eParser.parse(is);
...
eParser.foo();
eParser.bar();
}
public ExcelFileParser getExcelFileParser(){
...
}
}
How to write unit test for method m at this situation? I want to mock eParser object only.
Is it possible?
I use Mockito and PowerMockito
You can do what you want in Mockito (no PowerMock needed) using a spy without changing your code at all.
In your unit test you need to do something like the following:
ExcelFileParser parser = mock(ExcelFileParser.class);
MyClass myClass = spy(new MyClass());
doReturn(parser).when(myClass).getExcelFileParser();
Can you pass AnotherObject as a parameter into the method m rather than calling getAnotherObject() in the method itself?
Preface: I use EasyMock not Mockito so this may be a bit off.
Can't you create an inner subclass of MyClass in your test that overrides getExcelFileParser and has it return a mock? Like this:
public class MyClassMock extends MyClass {
ExcelFileParser _mock;
public MyClassMock(ExcelFileParser mock) {
_mock = mock;
}
#Override
public ExcelFileParser getExcelFileParser() {
return _mock;
}
}
I haven't tested this so there could be issues with this, but the basic idea should be right.

Java: How do I mock a method of a field when that field isn't exposed?

I'm using Java 6, JUnit 4.8.1, and writing a console application. My application has a member field that isn't exposed …
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
private void initServices() {
…
m_oppsSvc = new OpportunitiesServiceImpl(…);
}
...
}
I want to mock a behavior such that whenever one method from my service is called, (e.g. m_oppsSvc.getResults()), the same result is always returned. How do I do that? There's no setter method for the field. I'm currently working with Mockito 1.8.4. Is it possible to do this with Mockito or some other mock framework?
This is what you want:
#RunWith(MockitoJUnitRunner.class)
public class MyAppTest {
#Mock private OpportunitiesService mocked_m_oppsSvc;
#InjectMocks MyApp myApp;
#Test public void when_MyApp_uses_OpportunititesService_then_verify_something() {
// given
given( mocked_m_oppsSvc.whatever()).willReturn(...);
// when
myApp.isUsingTheOpportunitiesService(...);
// then
verify...
assertThat...
}
}
Using: Mockito 1.9.0, BDD style, FEST-Assert AssertJ.
Hope that helps :)
Given that you're already using mockito, why not just use reflection:
#RunWith(MockitoJUnitRunner.class)
public class MyApp {
#Mock
private OpportunitiesService m_oppsSvc;
private MyApp myApp;
#Before
public void before() throws Exception {
myApp = new MyApp();
Field f = MyApp.class.getDeclaredField("m_oppsSvc");
f.setAccessible(true);
f.set(myApp, m_oppsSvc);
}
}
It's a bit ugly, but it will do the trick. Note that this may not be the most efficient way to do it with Mockito, but it will work.
There's also Powermock which should allow you to do this as well using the Whitebox class. I won't get into the whole details of Powermock but here's the call to inject the private field value, which should be a mock object:
Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
You should consider attempts to mock a private field a smell. That is, a sign that either what you're trying to do is either incorrect or that your code is currently structured incorrectly. You should only need to mock public methods or injected dependencies
In the code you've given you should consider injecting OpportunitiesService as follows:
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
public MyApp(OpportunitiesService oppsSvc) {
this.m_oppsSvc = oppsSvc;
}
...
}
In your test you can then inject a mock as follows:
OpportunitiesService mockOpportunitiesService =
Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
You can easily do it with JMockit:
public class MyAppTest
{
#Tested MyApp myApp;
#Test
public testSomething(final #Capturing OpportunitiesService mockService)
{
new NonStrictExpectations() {{
mockService.getResults(); result = asList("a", "b", "C");
// record other expectations, if needed
}};
myApp.whateverMethodIWantToTest();
new Verifications() {{
mockService.doSomething(anyInt);
// verify other expectations, if needed
}};
}
}
Even though the implementation class OpportunitiesServiceImpl isn't mentioned in test code, its instances (any number of them) will still get properly mocked.
Generally you should use dependency injection and pass the mock object (of type OppportunitiesServiceImpl) in via the constructor, a separate setter or directly to the method (getResults). You might need to extract an interface for OpportunitiesServiceImpl first.
Usually, this is solved through the use of dependency injection. In regular (production) mode, your dependency injection container (e.g. Spring or Guice) will inject an instance of OpportunitiesService into MyApp through your constructor or through a setter.
Then, when you're testing you can "inject" a mock instance manually using the same setter or constructor argument.
Instead of doing
m_oppsSvc = new OpportunitiesServiceImpl(…);
Try Passing OpportunitesService in through MyApp's constructor

Categories

Resources