Is it a right case for Mockito spy? - java

Let's say I have a class
class SomeClass
{
public void methodA()
{}
public void methodB()
{}
public void someMethod()
{
methodA();
methodB();
}
}
I would like to test behavior of someMethod() with Mockito.
The only way I could think of is using spy();
Something like
SomeClass someClass = spy(new SomeClass());
someClass.someMethod();
InOrder inOrder = inOrder(someClass);
inOrder.verify(someClass).methodA();
inOrder.verify(someClass).methodB();
I'm new to the mockito and documentation says
"Real spies should be used carefully and occasionally, for example when dealing with legacy code."
So maybe I'm missing something and there is better (right) way to verify that methodA and methodB were called without explicitly calling them in the test case.
Thanks.

Yes, spy() is fit for your purpose. The warning is due to the fact that real methods are invoked, and hence you can get unexpected results (for example - real money being withdrawn from a bank account)

If your code needs spy for unit testing - something wrong.
Spy is a first sign of a code smell.
You have two options to avoid it in your example:
You can avoid mocking one of the method and test the whole someMethod.
If methodA and methodB is really needs to be mocked - you can move them to seperate class etc.

Related

Mocking constructor using powermock on the class which needs to be tested

I am able to mock a constructor call using powermock from inside a class which I want to test. This works when I add the class I want to test in #PrepareForTest. But once I add my class there, even when the test cases pass, the coverage is being shown as 0 in the coverage plugin.
When I remove my class from #PrepareForTest, of course, coverage starts showing up for other test cases but the test case in which I have to mock constructor call fails. Not sure what to do about this.
Class A
{
MyObject o;
A(){
//some other code
o = new MyObject();
//some other code
}
public void process(){
//some code
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
Class TestA{
#Test
public void test1()
{
MyObject mocked = Mockito.mock(MyObject.class);
PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(mocked);
A a = new A();
a.process();
//Assert as per test case
}
}
In coverage tool, coverage shows as 0 however, unit test passes and I checked in debug mode that it was covering all the statements of class A.
In coverage tool, coverage shows as 0 however, unit test passes and I checked in debug mode that it was covering all the statements of class A.
Coverage tools rely on manipulating the executed byte code.
So does PowerMock, when you mock static/new.
This can quickly lead to all sorts of problems. For JaCoCo, there seems to be a solution around offline instrumentation. Where, I also remember: some other person asked about that some time back, and in the end gave up, because he couldn't get "offline instrumentation" to work either.
For any other framework, I have to repeat old advice: consider to invest your time to learn how to write easy-to-test code. Because if you would do that, you would not need to use PowerMock(ito) in order to test it.
Your code is hard-to-test because of that new() statement in the constructor. Simply don't do that. Either use dependency injection via #InjectMocks, or have a test-only constructor that takes the required object.
Long story sort: when you write your own, new code, and you think you need PowerMock to test it, then you are doing something wrong.
I think you can do without Powermock here. If you Spy on class A and mock the getter you should end up with the same result and most likely have your coverage correct:
#Test
public void test1(){
MyObject mocked = Mockito.mock(MyObject.class);
A spyA = Mockito.spy(new A());
doReturn(mocked).when(spyA).getMyObject();
...
}

Mocking a non-abstract method of an abstract class

I am trying to unit-test a class that extends an abstract base class.
Here are the "similar classes" for illustration purposes:
public abstract class MyAbstractBaseClass {
#Autowired
private WaterFilter waterFilter;
protected List<String> filterComponents(List<String> allComponents) {
return waterFilter.filter(allComponents);
}
}
public class MyDerivedClass extends MyAbstractBaseClass {
public List<String> filterWater(List<String> allWaterComponents) {
List<String> filteredComponents = this.filterComponents(allWaterComponents); //calls abstract class's filterComponets()
filteredComponents.add("something-else");
return filteredComponents;
}
}
Here is the unit test I am trying:
#RunWith(EasyMockRunner.class)
public class MyDerivedClassTest {
#TestSubject
private MyDerivedClassTest SUT;
#Before
public void setup() {
SUT = new MyDerivedClassTest();
}
#Test
public void test filterWater_HappyCase() {
//I want to mock my abstract class's filterComponents() method
//I am trying this:
EasyMock.expect(SUT.filterComponents(getDummyComponents())).andReturn(getSomeComponents());
//What to replay here?
//EasyMock.replay(...)
List<String> actualResult = SUT.filterWater(getDummyComponents());
//assert something
//What to verify?
//EasyMock.verify(...)
}
}
When I run this test, I get
java.lang.NullPointerException
in MyAbstractBaseClass.filter(allComponents)
I understand that the autowired "waterFilter" is not getting initialized. But then, I just want to mock the "non-abstract" method of the abstract class in my unit test.
How should I go about this using EasyMock? Also, I don't know what to replay() and verify().
When you write an unit test, you test a object (generally, a method of it) and you may mock a object (generally, a method of it).
However, you should not unit test and mock the same object because in a some way, it seems not very natural : if you test a method of a class, the behavior of the tested class should stay as natural as possible and not fake its own methods.
Otherwise, we can wonder if the quality of the unit test is good.
Why ? Because it doesn't reflect the real behavior of the class that we would have at the runtime, but just some part of its behavior.
In a unit test, isolation is researched but behind it, the idea is to isolate your under test class only from the other classes and not an isolation of its own behavior.
Of course, you can try to mock a no-abstract method in the abstract class of your under tested class but the design and the quality of your test may become less good.
In your case, I imagine two reasons to mock the no-abstract method in the abstract class :
the waterFilter field dependency annoys you because it is not valued, so an exception (NullPointerException) is raised during the test.
You really want to mock the no abstract method in the abstract class because you have already unitary tested this method and you don't want to duplicate this test.
1) If your the problem is the waterFilter field dependency.
you should mock the waterFilter field. To mock a field, it must be accessible and modifiable. In your case, it's not straight because the field is private.
So, you have two ways to access to it to be able to mock it :
change your design to give the possibility to set the field from a public method or in the constructor of MyDerivedClass.
use reflection to set the field (use an API or do it yourself because it's not hard).
You don't need to do verify operations with EasyMock. Just mock the result returned by waterFilter.filter(allComponents) such as :
waterFilterMock.filter(mockedComponents)
In this way, the mock returns the value you have chosen and in your JUnit assertion, you are able to do the correct assertion for your method under test.
Just for information, you could use Mockito instead of EasyMock. It's more flexible and it offers more readable operations.
For example, you could do it with Mockito :
Mockito.when(waterFilterMock.filter()).thenReturn(mockedComponents);
As you can see, it is more readable.
2) If you problem is that you really want to mock the no-abstract method in the abstract class because you have already unitary tested it
You should modify your design and use composition instead of inheritance. You would have not MyAbstractBaseClass any longer but simply a dependency between two classes (the one has a field of the other). In this way, you could mock the filterComponents() method in a natural way.
Expectations has to be set on mocked resources.
In your case i think you should inject a mocked instance of WaterFilter.
And your expectation,replay and verify should be set on waterFilter object instance.
You can refer to the example provided in given below link.
http://www.tutorialspoint.com/easymock/easymock_junit_integration.htm

how to unit test methods with dependencies

I need to create some unit testing for my application but I am not sure how to proceed and I couldn't find anything of help online. What I want to know is how to test an app where there are many methods dependent on a few others.
e.g.
public class foo(){
public void doIt() {
boz();
bar();
biz.baz(); //from another class
}
public void bar(){
...
}
public int boz(){
...
}
}
so in a scenario like the one presented above one would think that unit testing the doIt method would be sufficient since it is going to fail anyway if something is wrong with the methods called inside it.
Although, I am not sure if we can consider this to be unit testing as this tests the functionality of more than just an entity. In addition, if the test on the doIt method fails it is going to be really hard to tell where the error occurred especially in a case with many dependencies - doesn't that defy the meaning of unit testing?
So far the only approach I have thought is to start by testing the dependencies first (i.e. bar boz baz) and then the doIt method. That way, if the test suite gets to doIt with no errors and fails means that there is something wrong with the code implemented inside that method and not inside its dependencies.
BUT, is this the right way of doing it?
To test doIt() method without having to invoke the real implementations of bar() and baz(), use a Spy in Mockito:
Mockito spy documentation
If bar() is really void, you can do something like this:
foo f = spy(new foo());
doNothing().when(foo).bar();
Better is if you can inject your dependencies (ex: biz) as mock objects and test your foo class directly.

Verifying sequence of private method calls in unit testing

I have the following class:
class MyClass {
public void doIt() {
methodOne();
methodTwo();
methodThree();
}
private void methodOne() {
// ...
}
// rest of methods similar...
}
My intention is to verify that when i invoke doIt(), methods metodOne(), methodTwo() and methodThree() will be invoked, in that order.
I'm using mockito for mocking. Does anyone knows how i can test this scenario?
Hate to be the person but: simply don't test this. Test the output, side effects, results - not the implementation.
If you really want to ensure the correct order, extract these methods into separate class(es) and mock them.
As long as your private methods are ... well ... private, don't test them. They are implementation details. They could be refactored without changing the contract of your class. Test the correct outcome of your public methods.

Abort test on super method call

I've got the following method
public void myMethod(final MyObject myObject) {
if (myObject.isDownload()) {
// Do something
} else {
super.myMethod();
}
}
I want to verify now in a JUnit test, that the super implementation has been called.
I also want to abort the test, if the super call has been performed, since the underlying implementation is very complicated and hard to test respectively mock.
I'm using Mockito as a mocking framework.
That sounds like a perfect use case for a mocking framework. Just mock your implementation of super in a way that it does nothing on a call to myMethod(). Verify that myMethod() was called on your mock in the unit test.
You could give Mockito a try. But there are several other good mocking frameworks for Java.

Categories