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.
Related
Want to ask you a question.
How should I properly return some data from method called from testable class ?
For example I have next structure:
Class SomeClass {
public void method1(){
//some logic here
List<Object> howToReturnHereValues = gatData();
//some logic here
}
public List<Object> getData(){
return List<Object>;
}
}
Right now I want to test method1(), but I don't know how to mock call getData() which returns List<Object>.
Any advice please ?
You can do this using a spy, like explained here: https://static.javadoc.io/org.mockito/mockito-core/2.7.17/org/mockito/Mockito.html#13
Example:
#Test
public void testMethod1() throws Exception {
SomeClass someClass = new SomeClass();
SomeClass spy = Mockito.spy(someClass);
Mockito.when(spy.getData()).thenReturn(Arrays.asList("blaat", "blabla"));
spy.method1();
}
This will return a List of "blaat" and "blabla" which can be used by the logic in your method1.
Right now I want to test method1(), but I don't know how to mock call
getData() which returns List.
It is rather a bad idea to mock a public method of a class that is under test.
A unit test should test a behavior and mock dependencies. Here, you unit test only a part of the behavior as you mock the behavior of the tested class.
If the class is ours you could :
either test this method without mocking the getData() called public method.
or move the getData() public method in another class and then mock this new dependency if you don't want to repeat the test of the getData() method in each test method calling it.
If the class is not modifiable and the mocked called is really required, you could use the spy() method of the Mockito framework on the object under test to simulate a mocked behavior for a specific method.
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.
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...
Following is my class
public class SomeClass {
public ReturnType1 testThisMethod(Type1 param1, Type2 param2) {
//some code
helperMethodPublic(param1,param2);
//more code follows
}
public ReturnType2 helperMethodPublic(Type1 param1, Type2 param2) {
//some code
}
}
So in the above class while testing testThisMethod(), I want to partially mock helperMethodPublic().
As of now, I am doing the following:
SomeClass someClassMock =
PowerMock.createPartialMock(SomeClass.class,"helperMethodPublic");
PowerMock.expectPrivate(someClassMock, "helperMethodPublic, param1, param2).
andReturn(returnObject);
The compiler doesn't complain. So I try to run my test and when the code hits the helperMethodPublic() method, the control goes into the method and starts to execute each line of code in there. How do I prevent this from happening?
Another solution that doesn't rely on a mock framework would be to override 'helperMethodPublic' in an anonymous subclass defined within your test:
SomeClass sc = new SomeClass() {
#Override
public ReturnType2 helperMethodPublic(Type1 p1, Type2 p2) {
return returnObject;
}
};
Then when you use this instance in your test it will run the original version of 'testThisMethod' and the overridden version of 'helperMethodPublic'
I think it is because of what Jeff said.
Try this - setting up an expectation just as any other mocked method:
SomeClass someClassMock = PowerMock.createPartialMock(SomeClass.class,
"helperMethodPublic");
EasyMock.expect(someClassMock.helperMethodPublic(param1, param2)).
andReturn(returnObject);
PowerMock.replayAll();
I would guess this is because your "helperMethodPublic" is not a private method (as in PowerMock.expectPrivate). PowerMock is a framework that extends other mocking frameworks to add things such as mocking private and static methods (which JMock, Mockito, etc don't handle). Doing a partial mock of public methods should be something your underlying mock framework handles.
I'm trying to mock a method of an object inside the class I'm testing.
For instance
class ClassToTest {
public doSomething () {
SomeObject a = new SomeObject ();
a.doSomethingElse ();
}
}
Is there a way to mock the methods of the variable "a"? I'd like doSomethingElse to do nothing during testing. I'm currently using Mockito but I'm open to any mocking framework.
Thanks
Yes, there is a way, as shown by the following JMockit test:
public void testDoSomething(final SomeObject mock)
{
new ClassToTest().doSomething();
new Verifications() {{ mock.doSomethingElse(); }};
}
No need to refactor code under test to use a wrapper, DI, etc; simply mock whatever you need to be mocked.
It's not possible to mock the reference "a" when it's declared as a local variable, as in your case. You could consider injecting the dependency to SomeObject, e.g. as a parameter of doSomething method. That way, you can inject a mock of SomeObject in your test instead.
One of the benefits of dependency injection is increased testability.
With some refactoring it is possible, of course:
class SomeObject {
public void doSomethingElse()
{
}
}
class ClassToTest
{
private final SomeObject someObject;
public void doSomething()
{
someObject.doSomethingElse();
}
public ClassToTest(SomeObject someObject)
{
this.someObject = someObject;
}
}
class Test {
#Test
public void testDoSomething()
{
SomeObject someObject = Mockito.mock(SomeObject.class);
new ClassToTest(someObject).doSomething();
Mockito.verify(someObject, Mockito.atLeastOnce()).doSomethingElse();
}
}
I believe you can use EasyMock Class Extensions for EasyMock 2.5 or earlier, and apparently it is included in 3.0. See this part of the previous page for information on what you are trying to do. That said, I haven't personally tried to do that, so I don't know how well it will work.
If you want a new instance in each call, I'd suggest refactoring in the following way:
class ClassToTest {
public doSomething () {
SomeObject a = getInstance();
a.doSomethingElse ();
}
protected SomeObject getInstance() {
return new SomeObject();
}
}
Then you can create a testclass extending ClassToTest, overriding the getInstance() method, with one supplying a mock object.
This is of course only viable if you are ok with exposing the getInstance() method, so I don't recommend it if the class is part of a public API. If this is the case, consider supplying a factory class using dependency injection.
class ClassToTest {
private SomethingElseInterface somethingElseDoer ;
public ClassToTest(SomethingElseInterface somethingElseDoer) {
this.somethingElseDoer = somethingElseDoer;
}
public doSomething () {
somethingElseDoer.doSomethingElse();
}
}
And where you use it:
SomethingElseInterface somethingElseDoer = ...; // in a test, this is where you mock it
ClassToTest foo = new ClassToTest(somethingElseDoer); // inject through constructor
foo.doSomething();