How to verify that a method is not called on an object's dependency?
For example:
public interface Dependency {
void someMethod();
}
public class Foo {
public bar(final Dependency d) {
...
}
}
With the Foo test:
public class FooTest {
#Test
public void dependencyIsNotCalled() {
final Foo foo = new Foo(...);
final Dependency dependency = mock(Dependency.class);
foo.bar(dependency);
**// verify here that someMethod was not called??**
}
}
Even more meaningful :
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
// ...
verify(dependency, never()).someMethod();
The documentation of this feature is there §4 "Verifying exact number of invocations / at least x / never", and the never javadoc is here.
Use the second argument on the Mockito.verify method, as in:
Mockito.verify(dependency, Mockito.times(0)).someMethod()
First of all: you should always import mockito static, this way the code will be much more readable (and intuitive):
import static org.mockito.Mockito.*;
There are actually many ways to achieve this, however it's (arguably) cleaner to use the
verify(yourMock, times(0)).someMethod();
method all over your tests, when on other Tests you use it to assert a certain amount of executions like this:
verify(yourMock, times(5)).someMethod();
Alternatives are:
verify(yourMock, never()).someMethod();
Alternatively - when you really want to make sure a certain mocked Object is actually NOT called at all - you can use:
verifyZeroInteractions(yourMock)
Please Note:
verifyZeroInteractions(Object... mocks) is Deprecated.
Since Version 3.0.1. The now recommended method is:
verifyNoInteractions(yourMock)
As a more general pattern to follow, I tend to use an #After block in the test:
#After
public void after() {
verifyNoMoreInteractions(<your mock1>, <your mock2>...);
}
Then the test is free to verify only what should be called.
Also, I found that I often forgot to check for "no interactions", only to later discover that things were being called that shouldn't have been.
So I find this pattern useful for catching all unexpected calls that haven't specifically been verified.
Both the verifyNoMoreInteractions() and verifyZeroInteractions() method internally have the same implementation as:
public static transient void verifyNoMoreInteractions(Object mocks[])
{
MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}
public static transient void verifyZeroInteractions(Object mocks[])
{
MOCKITO_CORE.verifyNoMoreInteractions(mocks);
}
so we can use any one of them on mock object or array of mock objects to check that no methods have been called using mock objects.
Just as a suggestion, if you want to be more aligned at syntax level with Behavior-driven development style there is BDDMockito:
You could use:
then(dependency).should(never()).someMethod();
As an equivalent replacement of:
verify(dependency, never()).someMethod();
Related
Below mentioned is the class that I need to test:
public class MyClass {
private String key;
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
}
public String getKey() {
return key;
}
}
Now I need to test this constructor, but am unable to mock this Third party API call. And the Test case would be as mentioned below :
public class MyClassTest{
#Test
public void test1(){
MyClass c = new MyClass(dummyconnection);
assertNotNull(c.getKey != null);
}
}
But this case would be giving me an error that ThirdPartyAPI Class is failing as the the connection object is mocked.
So I want to mock this ThirdPartyApi call. Is it possible using Easymock, powermock?
Simple: EasyMock does not support mocking static calls. So you can turn to PowerMock(ito) or JMockit in case you do not want to change your code.
But the better approach would be to understand that using static always leads to tight coupling between your classes, and that you want to make sure that this doesn't affect your ability to unit test your code.
In your case:
public MyClass(Connection con) {
key = ThirdPartyApi.getkey(con);
simply replace that with:
public MyClass(Connection con) {
this (ThirdPartyApi.getkey(con));
}
/** unit testing only */
MyClass(Key key) {
...
And voila, you got a constructor that you can call from your unit test - and now you simply pass a mocked key object. And your tests will no longer execute that static call - because you use the key-taking constructor in all your tests.
But you probably want another test case to make sure that calling the public constructor does what you expect it to do - and that could be to throw an exception because that static call fails.
Beyond that: I fully agree with the comments - the fact that your constructor is doing so much (including static calls) has a certain design smell on it.
I am a big fan of mockito, unfortunately for one of my projects which uses Java 8, it fails on me...
Scenario:
public final class MockTest
{
#Test
public void testDefaultMethodsWithMocks()
{
final Foo foo = mock(Foo.class);
//when(foo.bar()).thenCallRealMethod();
assertThat(foo.bar()).isEqualTo(42);
}
#FunctionalInterface
private interface Foo
{
int foo();
default int bar()
{
return 42;
}
}
}
Unfortunately, the test fails and foo.bar() returns 0.
When I uncomment the when() line, I get a stack trace...
java.lang.NoSuchMethodError: java.lang.Object.bar()I
at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)
This is the latest stable version available on maven; googling around didn't tell me much about the status of mockito with regards to this new functionality in Java 8...
Can you make it work in some other way than implementing interfaces and spy() on them (this works)?
With mockito 2.x, JDK 8 default methods are supported.
With mockito 1.x it's not possible,
Old answer
Unfortunately it's not yet possible (mockito 1.10.19), from the README.md on the github'page
JDK8 status
Mockito should work fine with JDK8 if you stay away from default methods (aka defender methods). Lambda usage may work just as good for Answers. We're unsure about every JDK8 features at the moment, like serializing a mock that uses a lambda. Error report and pull request are welcome though (contributing guide).
EDIT 1: defender methods and default methods are different names for the same thing.
I hope for a mockmaker replacement that will handle java 8 opcodes properly for such cases as some opcodes have a different semantic in Java 8.
EDIT 2: Updated the mockito readme, and this quote accordingly
I just tried Mockito 2.0.38-beta, and it already works in that version. But Mockito must be told explicitly to call the default implementation.
Foo foo = mock(Foo.class);
assertThat(foo.bar()).isEqualTo(0);
when(foo.bar()).thenCallRealMethod();
assertThat(foo.bar()).isEqualTo(42);
Mockito (this works on version 3) can use default methods. Here's the example code rewritten with JUnit 5 so it should work:
#ExtendWith(MockitoExtension.class)
class MockTest {
#Mock(answer = Answers.CALLS_REAL_METHODS)
private Foo foo;
#Test
void testDefaultMethodsWithMocks() {
assertThat(foo.bar()).isEqualTo(42);
}
#FunctionalInterface
private interface Foo {
int foo();
default int bar() {
return 42;
}
}
}
The calls real methods answer DOES work in the latest Mockito. As a general rule, the extensions make the creation of mocks more declarative, but the mock method also provides an overload which supports the default answer as shown in the #Mock annotation above: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mock-java.lang.Class-org.mockito.stubbing.Answer-
You can get around this limitation by implementing the interface (tested in Mockito 1.10.19):
public class TestClass {
#Mock ImplementsIntWithDefaultMethods someObject;
#Test public void test() throws Exception {
// calling default method on mocked subtype works
someObject.callDefaultMethod();
}
/* Type that implements the interface */
static class ImplementsIntWithDefaultMethods implements IntWithDefaultMethod { }
/* Interface you need mocked */
interface IntWithDefaultMethod {
default void callDefaultMethod { }
}
}
I just ran into the same issue with Mockito (org.mockito:mockito-core:1.10.19). Problem is: I'm not able to change the Mockito version (2.7.22 would work) because of dependencies to org.springframework.boot:spring-boot-starter-test:1.4.3.RELEASE which we are using (Spring, Mockito issue).
The easiest solution I found is to implement the interface with a private abstract class within my test class and mocking that one (also compare to the solution of #Mihai Bojin). Doing it like this keeps you away from the hassle to also "implement" all methods required by the interface(s).
MWE:
public interface InterfaceWithDefaults implements SomeOtherInterface {
default int someConstantWithoutSense() {
return 11;
}
}
public class SomeTest {
private abstract class Dummy implements InterfaceWithDefaults {}
#Test
public void testConstant() {
InterfaceWithDefaults iwd = Mockito.mock(Dummy.class);
Assert.assertEquals(11, iwd.someConstantWithoutSense());
}
}
Another solution would be to use a Spy as described here: https://stackoverflow.com/a/54915791/3636822
Just a litte side note that especially functional interfaces can be easily created without mocking. If you need to call some verify methods afterwards, you may wrap the instance into a spy.
public final class MockTest
{
#Test
public void testDefaultMethodsWithMocks()
{
final Foo foo = () -> 0;
assertThat(foo.bar()).isEqualTo(42);
}
#FunctionalInterface
private interface Foo
{
int foo();
default int bar()
{
return 42;
}
}
}
Sometimes we are so used to work with these frameworks that we easily forget about the obvious solutions.
I'll show my problem using this example:
I have a class with a method foo. That class has a subclass which overrides this method.
Subclass' method calls superclass' method. Can I verify that?
I don't want to test what foo in superclass does. I just need to verify that it was called.
I know that refactoring could help (favour composition over inheritance, etc) but I am unable to do that.
Is there any way to achieve what I need?
Below is simple example of what I've tried
package tmp;
import org.junit.Test;
import org.mockito.Mockito;
import static org.mockito.Mockito.times;
public class Example {
#Test
public void test() {
// given
ChildClass childClass = new ChildClass();
ChildClass spyChildClass = Mockito.spy(childClass);
// when
spyChildClass.foo(100);
// then
Mockito.verify((BaseClass) spyChildClass, times(1)).foo(101);
}
}
abstract class BaseClass {
public void foo(int n) {
System.out.printf("BaseClass.foo(%d)%n", n);
}
}
class ChildClass extends BaseClass {
#Override
public void foo(int n) {
System.out.printf("ChildClass.foo(%d)%n", n);
super.foo(n + 1);
}
}
And this is the result:
ChildClass.foo(100)
BaseClass.foo(101)
Argument(s) are different! Wanted:
childClass.foo(101);
-> at tmp.Example.test(Example.java:19)
Actual invocation has different arguments:
childClass.foo(100);
-> at tmp.Example.test(Example.java:16)
Expected :childClass.foo(101);
Actual :childClass.foo(100);
<Click to see difference>
Obviously it's not what I wanted to see.
I can't modify BaseClass. I don't want to test BaseClass (I am not responsible for it). I don't even neet to know what exactly it does. I just need to verify that its method was called. Wnything else is not my problem. Its the problem of people who maintain BaseClass.
Test the behaviour of the class, not it's implementation.
Write the test such that the method is called and is expected to do something. Next check the object now represents what you now expect it to represent.
If BaseClass.foo is expected to increment some counter by 100, yet Subclass.foo increments some counter by 50 then calls the superclass, verify that the counter is now 150 and not just 50.
Don't peek the how - they may change over time. Do test the behaviour. The method foo may do other things besides increase counters - check the state of the object not what it did.
Possible solution: Make foo final, and decree that subclasses need to override some other method, the implementation of foo, instead of the actual foo.
abstract class BaseClass {
private boolean myFooCalled;
public final void foo(int n) {
myFooCalled = false;
fooImpl(int n);
if (!myFooCalled) { ... }
}
public void fooImpl(int n) {
myFooCalled = true;
System.out.printf("BaseClass.foo(%d)%n", n);
}
}
Notes: This is off the top of my head, so (1) I haven't tested it, (2) I'm not sure if this is what you really want, (3) I'm not sure whether your design ought to be improved. This is a general answer about "how you could make sure an overriding method calls the superclass method", not an answer tailored to your purposes.
I hesitate to give this answer because everyone here (including the OP) knows you can do this... but to answer the OP's question you can do this:
Instead of having
#Override
public void reset() throws IOException{
// ...
super.reset();
}
do this:
#Override
public void reset() throws IOException{
// ...
callSuperReset();
}
void callSuperReset() throws IOException {
super.reset();
}
... and verify that callSuperReset was indeed called...
I am a mocking newb (no doubt it shows), and I thought for a long time the command was simply "Thou shalt not create methods just to suit your tests".
But in a previous question of mine, davidxxx in his answer says
In fact I would say rather : "thou shalt not create methods to suit
your tests and that open the API of the application in an undesirable
way"
Given that this method callSuperReset is package-private, is there any problem in principle with it? (other than its total inelegance)
Yes, such a test can be written. And there is nothing wrong with wanting to do it, provided what you are testing is the contract of an API, not its implementation.
Here is a test for the contrived example in the question, using the JMockit mocking API:
#Test
public void subclassShouldObeyContractOfBaseClass(
#Mocked final BaseClass anyBaseInstance)
{
new ChildClass().foo(123);
new Verifications() {{ anyBaseInstance.foo(anyInt); }};
}
If necessary (as dictated by the contract of BaseClass#foo(int)), the test could also verify the argument value passed to the base method as being n + 1 (or whatever).
I want to make a JUnit test to assure that some classes don't use a specific set of methods (from another classes). Example
class MyClass
{
void myMethod()
{
otherClass.otherClassStaticMethod();
}
}
class myTest
{
void test()
{
assertFalse(CalledMethods.getMethodsCalledBy("myClass.myMethod").Contains("otherClass.otherClassStaticMethod"));
}
}
In this test I want to assure that myMethod doesn't invocate otherClassStaticMethod. How can I find what methods are being called inside a method in compile time (ignore methods called using reflection)? I thought about a .java parser, do you recommend any?
you can mock "otherClass" and verify that the method isn't invoked. E.g. using Mockito you can even specify in which order what methods are supposed to be invoked (under the condition their instances are mocks) and specify which methods are not allowed to be invoked
as coding.mof said, to mock static methods you should use PowerMock/PowerMockito:
example:
PowerMockito.mockStatic(OtherClass.class);
PowerMockito.verifyStatic(never());
OtherClass.otherClassStaticMethod();
It sounds like you should be using a mock library and let that handle it all for you. I'd recommend JMock as my library of choice. If you're using instance methods then this would be perfect for you - if, as your example shows, it's static methods then PowerMock may work*1.
With JMock, you'd have something like:
public class MyClass {
public MyClass(Dependency dependency) {
this.dependency = dependency;
}
void myMethod() {
dependency.someMethod();
}
}
#RunWith(JMock.class)
public class MyTest {
private Mockery context = new Mockery();
#Test
public void doesNotCallSomeMethod() {
Dependency dependency = context.mock(Dependency.class);
MyClass obj = new MyClass(dependency);
obj.myMethod(); <--- this will fail fast
}
}
When you call obj.myMethod, JMock will instantly report that you never said dependency should have any methods called. It will also tell you what method you DID call and what parameters you passed in if any
*1 I don't use PowerMock as I steer away from static methods unless they are pure functions
Sometimes, you want to test a class method and you want to do an expectation on a call of a super class method. I did not found a way to do this expectation in java using easymock or jmock (and I think it is not possible).
There is a (relative) clean solution, to create a delegate with the super class method logic and then set expectations on it, but I don't know why and when use that solution ¿any ideas/examples?
Thanks
Well, you can if you want to. I don't know if you are familiar with JMockit, go check it out. The current version is 0.999.17 In the mean time, let's take a look at it...
Assume the following class hierarchy:
public class Bar {
public void bar() {
System.out.println("Bar#bar()");
}
}
public class Foo extends Bar {
public void bar() {
super.bar();
System.out.println("Foo#bar()");
}
}
Then, using JMockit in your FooTest.java you can validate that you're actually making a call to Bar from Foo.
#MockClass(realClass = Bar.class)
public static class MockBar {
private boolean barCalled = false;
#Mock
public void bar() {
this.barCalled = true;
System.out.println("mocked bar");
}
}
#Test
public void barShouldCallSuperBar() {
MockBar mockBar = new MockBar();
Mockit.setUpMock(Bar.class, mockBar);
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
Mockit.tearDownMocks();
}
Expanding on #Cem Catikkas answer, using JMockit 1.22:
#Test
public void barShouldCallSuperBar() {
new MockUp<Bar>() {
#Mock
public void bar() {
barCalled = true;
System.out.println("mocked bar");
}
};
Foo foo = new Foo();
foo.bar();
Assert.assertTrue(mockBar.barCalled);
}
No need for the static class annotated with #MockClass, it is replaced by the MockUp class.
I don't think I'd mock out a super call - it feels to me like the behaviour there is part of the behaviour of the class itself, rather than the behaviour of a dependency. Mocking always feels like it should be to do with dependencies more than anything else.
Do you have a good example of the kind of call you want to mock out? If you want to mock out a call like this, would it be worth considering composition instead of inheritance?
There are several tests that do just that (ie specify an expected invocation on a super-class method) using the JMockit Expectations API, in the Animated Transitions sample test suite. For example, the FadeInTest test case.
No, there is no way of mocking super class methods with jMock.
However there is a quick-and-dirty solution to your problem. Suppose you have class A and class B extends A. You want to mock method A.a() on B. You can introduce class C extends B in your test code and override the method C.a() (just call super, or return null, id does not matter). After that mock C and use the mock everywhere, where you'd use B.
intercepting a super call is much too fine-grained. Don't overdo the isolation.