Mockito method call without object - java

The code has something like
Speed speed = readSpeed(Point A, Point B);
isOverLimit = limitCheck.speedCheck(speed);
How do I use mockito for read speed?
Mockito.when(readSpeed(0, 0).then...
suppose should I use the class object to call this?

Mockito effectively works by creating individual subclasses of objects that delegate every overridable implementation to the mock framework.
Consequently, you can't use Mockito mock your method (readSpeed) for all instances at once or instances created in your system under test, nor mock any static or final methods. If readSpeed is any of those, or need to be mocked on an instance you don't touch in your test, Mockito will not work for you; you'll need to refactor, or use PowerMockito (which quietly rewrites your system under test to redirect constructors, final calls, and static calls to Mockito's framework).
If readSpeed is a public non-final instance method on your system under test, then you can mock it, and that'd be called a partial mock of your component. Partial mocks can be useful, but can also be considered "code smells" (as mentioned in the Mockito documentation): Ideally your test class should be an atomic unit to test, and mocking should happen for the dependencies around your system under test rather than your test itself. Otherwise, you could too easily test the spec or test the mocking framework rather than testing your component.
Though the better thing to do would be to split the class into smaller interconnected components, you can use partial mocking in Mockito like this:
#Test public void componentChecksSpeed() {
YourComponent yourComponent = Mockito.spy(new YourComponent());
// Use doReturn, because the when syntax would actually invoke readSpeed.
doReturn(65).when(yourComponent).readSpeed(any(Point.class), any(Point.class));
yourComponent.run();
}

Related

Limitations of Mockito

I know that Mockito doesn't support mocking of local variables, static methods and private methods. Is there any way to get around it.
Like in the case of private methods changing the method from private will do or we could change it to a protected interface so that we could write test scripts. So do we have anything like this for static methods and local variables.
https://github.com/mockito/mockito/wiki/FAQ says the limitations of Mockito. Can any Mockito guru let me if it got any other limitations and how to overcome them I mean by refactoring. Thank you.
The best way to avoid the limitations of Mockito is to not insist on writing isolated unit tests.
Contrary to what some think, unit tests do not need to run in isolation from the dependencies of the tested unit. As described by Martin Fowler (and as practiced by Kent Beck, the "father" of TDD), unit tests can be "sociable" (with no mocking of dependencies) or "solitary" (with mocked dependencies).
So, one way to avoid those mocking tool limitations is to simply not rely on them. You can do that by writing "sociable" unit tests, or (like I do) go the whole way and write integration tests.
The other "solution" that was mentioned is to refactor the code under test in order to work around mocking limitations, or to "design for mocking" (as Jeff Bowman said).
I hope most developers realize this is a bad solution, as it usually requires adding extra complexity to the SUT, just to make up for arbitrary limitations in a particular mocking library.
Consider the case of increasing the accessibility of a private method so you can test it directly or mock it. Well, if you find that acceptable, do you really care about code quality? And if you don't care, then why bother with automated developer testing anyway?
To help understand Mockito's limitations, it's important to realize what Mockito is doing for you: Mockito creates a dynamic (proxy-based) subclass of the class you pass in. This means that, like a subclass you would write yourself, you won't have access or control over private fields and methods, static methods, and local variables. There is no workaround.
You mentioned PowerMock in the comments, which works around some of the Mockito limitations by rewriting the bytecode of the class you want to mock, or the class that consumes a class you want to mock. This allows PowerMock to intercept calls that you can't override via polymorphism, particularly private, static, and final fields. You also won't have access to local variables.
Your best bet is, instead, to restructure your class or method so that it does give you the control you want. In general you should be asking "would I be able to do this if I created my own subclass", and that answer will help determine whether Mockito can automate it for you.
(Note that below I've referred to "designed for mocking", but what you're really doing is designing for alternative implementations of your dependencies; mocks are just one example of this, along with a variety of other test doubles like fake or in-memory implementations. Remember that not everything needs to be mocked or substituted for your test to remain a unit test; just make sure your dependencies in tests are fast, deterministic, and well-tested. Conversely, for slow, nondeterministic, poorly-tested, or yet-unwritten components, substituting an implementation with a fake or mock may improve test quality and coverage.)
public class NotDesignedForMocking {
public int yourMethod() {
Calculator calculator = new Calculator(); // impossible to mock!
return calculator.calculate();
}
}
One technique is to pass in your dependency as a method parameter.
public class DesignedForMockingViaMethodLevelDependencyInjection {
public int yourMethod() {
return yourMethod(new Calculator());
}
// Call this from tests instead; you can pass in a mock.
int yourMethod(Calculator calculator) {
return calculator.calculate();
}
}
Another is to switch to full dependency injection:
public class DesignedForMockingViaFullDependencyInjection {
private final Calculator calculator;
public DesignedForMockingViaFullDependencyInjection() {
this(new Calculator());
}
// Create objects in your test with this, so you can pass in a mock Calculator.
DesignedForMockingViaFullDependencyInjection(Calculator calculator) {
this.calculator = calculator;
}
int yourMethod() {
return calculator.calculate();
}
}
Finally, you can create an overridable factory method, which introduces the polymorphism that Mockito needs for its subclass-based overrides.
public class DesignedForMockingWithOverridableFactoryMethod {
public int yourMethod() {
Calculator calculator = createCalculator();
return calculator.calculate();
}
// Create an anonymous override in your class, or use a Mockito spy to intercept
// and override the behavior.
protected Calculator createCalculator() {
return new Calculator();
}
}
See also: How to use Mockito when we cannot pass a mock object to an instance of a class

Mock is not applied on new object creation

I was trying to mock a new object creation
public class MyServiceTest {
MyClass myClass;
myClass = Mockito.mock(MyClass.class);
Mockito.when(new MyClass()).thenReturn(myClass);
}
Error:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods cannot be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
I did mock the myClass object, but it is getting assigned to a new object on method call:
public class MyService {
public static String myMethod(){
MyClass myClass = new MyClass();
//..........
}
}
First: I recommend to not use PowerMock. As using this framework often results in bizarre errors, and: you have to understand that you are not facing a "deficiency" of Mockito ... but a deficiency in your design.
Basically, you want to learn about using dependency injection. The whole idea is: you do not call new within your production code. Because, you can't mock calling "new". Instead, you push the objects that your production code needs ... into your classes.
For normal (production) work, you push normal objects; and for unit testing, you push in mocked objects.
In other words: if you figure that your design would require PowerMock to be tested; then that tells you that your design needs to be reworked.
This is correct behavior; Mockito doesn't support mocking new object creation. You'll need another library like PowerMock for that, or you'll need to refactor your test.
To learn a little more about each part of a Mockito-based test:
/* 1 */ MyObject myObjectMock = Mockito.mock(MyObject.class);
/* 2 */ when(myObjectMock.methodCall()).thenReturn("return value");
/* 3 */ MySystemUnderTest systemUnderTest = new MySystemUnderTest(myObjectMock);
/* 4 */ systemUnderTest.methodToTest();
/* 5 */ verify(myObjectMock).methodCalledByTheSystemUnderTest();
mock creates a mock object. Note that you're not setting expectations on all instances of MyObject; instead, you're creating a single instance to control. Internally, this is actually a one-off subclass of MyObject with all its methods overridden, so Mockito is only really good for visible non-final instance methods (that you could override yourself).
You can use the when call to stub behavior. The only thing that can go inside when is a single call to a method on a Mockito-created mock, so your new keyword won't work here.
Again, because you can't use new, you'll generally need to insert your mock into your system under test. You (almost) never mock the system under test; you're mocking the collaborator instead, and since you can't use new you generally have to pass it in. This is part of why Mockito works so well with dependency injection systems.
Then you call your method-under-test...
...and check that the final state is what you want it to be. This can be assertions like assertEquals from a test framework, calls to verify using Mockito-created mocks, or some combination of the two.
Remember, with just Mockito, you will not be able to have Java return a mock when calling new, so you'll need a step like step 3 above. Alternatively, PowerMock is an extension library on top of EasyMock or Mockito, which has static methods like whenNew and mockStatic for more advanced mocking. (A word of caution, though: Because PowerMock uses a special classloader to rewrite your classes, it can be more difficult to set up, and its magic may make your tests harder to reason about. Refactoring may be a better way to keep your tests understandable.)
You can try powermock. It worked for me.
import org.powermock.api.mockito.PowerMockito;
MyClass myClassMock = Mockito.spy(new MyClass());
PowerMockito.whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
public class MyServiceTest {
MyClass myClass;
myClass = PowerMockito.mock(MyClass.class);
PowerMockito.whenNew(MyClass.class).thenReturn(myClass);
}

Static factory methods and mocking

How do you reconcile using static factory methods and mocking?
Many people would just say: Don't use static factory methods, use DI instead.
Well, sometimes you cannot avoid static factory methods. Consider the following use cases, which should be familiar:
Imagine you have a class called Option, like in scala. You can't avoid using a static factory method if you want to reuse same instance for all absent values.
As soon as you go new Option(null) you create a new option object, you cannot return the same object over and over again.
Similar use case is the Integer.valueOf() which will reuse integer objects for values below 128. Impossible to do without using a static factory method.
Another advantage is that factory methods are more descriptive than new keyword.
So how do you guys deal with having to use static factory methods and at the same time wanting to use inheritance and mocks?
Thank you.
Since it's a theorical question, I will make a theorical answer. The factory paradigm is the building point for another theory: the Injection. If your created objects are injected when needed, then you only have to inject your mocked objects to do all your tests. There alot of good books / web pages that can help you to get started on that.
Mocking out static methods is possible using PowerMock. Consider the following example from their Wiki page:
#Test
public void testRegisterService() throws Exception {
long expectedId = 42;
// We create a new instance of test class under test as usually.
ServiceRegistartor tested = new ServiceRegistartor();
// This is the way to tell PowerMock to mock all static methods of a
// given class
mockStatic(IdGenerator.class);
/*
* The static method call to IdGenerator.generateNewId() expectation.
* This is why we need PowerMock.
*/
expect(IdGenerator.generateNewId()).andReturn(expectedId);
// Note how we replay the class, not the instance!
replay(IdGenerator.class);
long actualId = tested.registerService(new Object());
// Note how we verify the class, not the instance!
verify(IdGenerator.class);
// Assert that the ID is correct
assertEquals(expectedId, actualId);
}
It's even possible to mock out only one particular method and leave the rest as is, using partial mocking.
My first option is to avoid the need to mock anything, so having static factory methods or not makes no difference.
That said, if I do want or need to mock them, then I just do it. For example, consider you are testing a JSF-based web application, and you want to mock the javax.faces.context.FacesContext object. I would write the following in a test, using the JMockit library (which I happen to develop):
#Test
public void exampleTest(#Mocked final FacesContext ctx) {
// Call the code under test, which will at some point
// call FacesContext.getCurrentInstance(), then add an
// error message for display in the web page.
new Verifications() {{
FacesMessage msg;
ctx.addMessage(null, msg = withCapture());
assertEquals("The expected error message.", msg.getSummary());
assertNotNull(msg.getDetail());
}};
}
In this example, Faces.getCurrentInstance() is the static factory method, which will automatically return a mock FacesContext instance once the class is mocked.
We simply avoid using static factory methods and we use dependency injection instead.
If java had been designed with DI in mind from the start, then Integer.valueOf() would have been:
integerType.valueOf() where integerType would be an injected dependency, or
typeSystem.getInteger().valueOf() where typeSystem would be an injected dependency, or
environment.getTypeSystem().getInteger().getFactory() where environment would be an injected dependency.
There is nothing that you can do with static factories that you cannot do with diligent use of dependency injection.
Now, once someone makes something available only via a static factory method, they are essentially coercing you to take the static road. This is unfortunate. But you can still wrap the static stuff in instances of your own device, and then inject those instances as dependencies into your production code, and then have your unit tests exercise those instances, avoiding the need to do such ungodly hacks as mocking static methods.
For example, you can wrap System.out in some StandardConsole object implementing some Console interface, and inject that Console interface as a dependency into your application.
(And if you do that, I would even add that you may proceed and configure your version control system to reject any attempts to commit code containing the string "System.out". [evil grin])

Passing mocked static method to another class

I have mocked a static method of a class using Powermock in my test class. The problem I face is that this static method is not called directly in my test class, but in some other class. Here is the skeleton:
#Test public void myTest() {
PowerMockito.mockStatic(MyClassWithStaticMethod.class);
PowerMockito.when(MyClassWithStaticMethod.staticMethod()).thenReturn("...");
List<String> details = MyHelperClass.getDetails();
...
...
}
Now MyHelperClass.getDetails calls the method that needs to be mocked as it is dependent upon a service.
MyHelperClass.java
public static List<String> getDetails() {
...
...
MyObj obj = MyClassWithStaticMethod.staticMethod(); //This needs to return mocked value
...
...
}
Is there a way to pass the mocked object to the helper class? PowerMockito.mockStatic returns void, where as PowerMockito.mock doesn't mock the static methods. So I am not able to figure out how to pass the mocked object to the helper class getDetails() method.
PowerMock isn't really capable of what you're willing to achieve. There's another mocking framework, that can mock literally almost everything by instrumenting the bytecode - JMockit
As for your problem - perhaps that would help
Just a simple note regarding static methods - since this kind of methods is harder to stub and since stubbing them can potentially affect other tests, I recommend adding unit tests for them and relying on those tests instead of trying to make sure the method is called.
The reason I'm advocating on this approach is that static methods should consist only of utility methods, which once tested can be relied upon. And also checking method calls always introduces coupling between your code and the unit tests, resulting in headaches when thinking about refactoring, as application code refactoring leads to lots of unit tests needing changes.

Mockito Mocking a return value and verify it

I have this class and wants to create a mock to return and verify the return value "50":
QAService.java:
#Path("/QAService")
public class QAService {
#GET()
//#Path("/")
#Produces("text/plain")
public String getServiceInfo() {
return "50";
}
My understanding of mock by defintion is that I can create a fake object of an implementation class and mock functions yet to be developed so I can test the interface.
Still I am creating this test to test mocking without having an interface. How do I verify it?:
QAServiceTest.java:
public class QAServiceTest {
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
}
Junit will only run methods annotated with #Test, so add it
#Test
public void getserviceTest () {
QAService qasmock = mock(QAService.class);
when(qasmock.getServiceInfo()).thenReturn("50");
String expected = "50";
assertEquals(expected, qasmock.getServiceInfo());
}
Also, you should verify() that your mock expectations actually happened.
verify(qasmock, times(1)).getServiceInfo();
Note that it seems like you want to test QAService, but you really aren't doing that here. You are simply testing a mock. That's not the same thing.
Create the QAService object yourself and use it.
Let's get a couple definitions straight, first:
A unit test is a brief bit of code you write to ensure that the system you've developed is behaving correctly. Unit tests are often created in a framework like JUnit, but do not need to be. For example, a unit test would assertEquals(5, calculator.add(2, 3)).
A mock is an imitation of a real system, which is often used in unit tests. Mocks are often created in frameworks like Mockito or EasyMock, but do not need to be. Mocks are a form of "test double"—the general term for code you substitute in place of your actual systems, for testing purposes—and Martin Fowler defines them more exactly in an article called "Mocks Aren't Stubs".
When writing a unit test, you're trying to test a single unit, which is often called the system under test or SUT for short. Each test will probably have a different system under test, and the point is that the code that you are testing in the test is your real, actual code, not any sort of mock or fake implementation.
In a complex application, your classes will probably need to collaborate with other classes that may or may not be written or tested, which are categorically known as dependencies. Any given class or system may have its own dependencies, and may be a dependency for other systems. Mocking frameworks are good for mocking those dependencies, not for mocking the system under test.
For your example, QAService is the main class you're writing (system under test), and QAServiceTest is the unit test for that system. No mocks are necessarily required.
Let's say that QAService depends on another class not yet written, called "StorageService". You don't necessarily want to wait for StorageService to work before writing QAService's tests, so instead of using a real StorageService you use a mock. Again, in the unit test called QAServiceTest, you use a real QAService and mock its dependency StorageService.
Even though you don't have StorageService written, you probably have some expectation about how QAService will use that class. Maybe you know that when you call storageService.store(qaRecord), it should return a numeric ID like 101. Even without the code working, you can create a Mockito mockStorageService, and prepare it like this:
when(mockStorageService.store(expectedQARecord)).thenReturn(101);
Now let's say that at the end of the test, you want to ensure that the method of QAService that you're testing will absolutely call storageService.delete(101). A Mockito mockStorageService would check that like this:
verify(mockStorageService).delete(101);
It is often unnecessary to verify statements you have made with when, because the test is unlikely to succeed unless the system under test calls the mock correctly to get that return value (101 here).
Now let's say that you've written another block of code called QAApplication, which you're testing in a unit test called QAApplicationTest, that depends on QAService. You may not have QAService finished or tested, and using a real QAService would require a StorageService, so instead you use mock QAService with a real QAApplication in your unit test called QAApplicationTest.
So, to sum up, a mock works within unit tests to mock the dependencies of the system under test. In your situation, QAServiceTest will not need a mock QAService, but may be used to mock the dependencies of QAService. If you do need a mock QAService, you'll need it when testing another class where QAService itself is a dependency.

Categories

Resources