I'm using Kotlin 1.6.10, Mockito 4.0.0 and Java 8 and I have a Java interface defined like this:
public interface MyInterface {
<D, T extends MyObject<T, D>> T doThings(T myObject);
}
An implementation of this interface is used in a Kotlin application and we have a unit test in which we want to make sure that the doThings method is never called using Mockito. In Java I would just do like this:
verify(myInterfaceInstance, never()).doThings(any());
But if I do this in Kotlin I get a compile-time error:
verify(myInterfaceInstance, never()).doThings(any())
Not enough information to infer type variable D
I understand why this is the case, but I cannot get it to work. In this particular case I really don't care about the generic types, I just want to make sure the doThings is never called. I've tried a lot of different things, for example:
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, Any>>(any())
which fails with:
Type argument is not within its bounds.
Expected:
MyObject<MyObject<*, Any>!, TypeVariable(D)!>!
Found:
MyObject<*, Any!>!
and I've also tried:
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, *>>(any())
and several other permutations which all seem to fail with roughly the same error message.
So my question is, how can I do the equivalent of Java's verify(myInterfaceInstance, never()).doThings(any()); in Kotlin?
This compiles fine, but issues a couple of warnings, you could suppress them via respectful annotation:
#Suppress("TYPE_MISMATCH_WARNING", "UPPER_BOUND_VIOLATED_WARNING")
verify(myInterfaceInstance, never()).doThings<Any, MyObject<*, *>?>(any<MyObject<*, *>>())
This is not a Mockito answer, but would the Library Mockk help you? MockK is built specifically for Kotlin so it might have better supports for Generics handling.
The verification would look like:
verify(exactly = 0) { yourClass.doThings(any()) };
https://notwoods.github.io/mockk-guidebook/docs/mocking/verify/
https://mockk.io/#verification-atleast-atmost-or-exactly-times
Related
I'm trying to port a Scala system to Mockito2. There are a few test cases that use doReturn and now in Mockito 2.18.0 I get this error:
Error:(34, 5) ambiguous reference to overloaded definition,
both method doReturn in object Mockito of type (x$1: Any, x$2: Object*)org.mockito.stubbing.Stubber
and method doReturn in object Mockito of type (x$1: Any)org.mockito.stubbing.Stubber
match argument types (com.twitter.util.Future[Unit])
doReturn(Future.Unit).when(f.adapterSpy).myFunction(userData, Some(offerId), Always)
Looking in Mockito.java, doReturn is really overloaded like that:
public static Stubber doReturn(Object toBeReturned)
public static Stubber doReturn(Object toBeReturned, Object... toBeReturnedNext)
How on Earth is this not always ambiguous? How do I make it compile?
Thanks
As a temporary workaround, you can do the following:
trait MockitoHelper extends MockitoSugar {
def doReturn(toBeReturned: Any): Stubber = {
Mockito.doReturn(toBeReturned, Nil: _*)
}
}
Then have your test mixin this MockitoHelper.
This can also be overcome by using doAnswer instead of doReturn
// no good
doReturn(true).when(foo).bar()
// works
doAnswer(_ => true).when(foo).bar()
There is a ticket in the Scala backlog on it. see https://github.com/scala/bug/issues/4775
This is a bit of self promotion but I just published a library called mockito-scala that solves this issue and many more, is part of the mockito ecosystem so hopefully should become the default when working with Scala, you can find it here https://github.com/mockito/mockito-scala with the information to get the dependency and what problems does it actually solves.
Specifically for your problem, you could write this code and it would work out of the box
doReturn(Future.successful(())).when(f.adapterSpy).myFunction(userData, Some(offerId), Always)
I changed the way the future is expressed just because is the correct way to create a completed future of Unit
There is a library/framework I use a lot that has some methods like this:
public IModel<?> getDefaultModel() { /* implementation here */ }
Using this method is fine, but sometimes I want to then call container.getDefaultModel().getObject().foo(). However, because getDefaultModel() returns an IModel<?> that means that getObject() returns an Object.
So I'm forced to use:
((Bar)container.getDefaultModel().getObject()).foo()
or
((IModel<Bar>)container.getDefaultModel()).getObject().foo()
But if the method had been specified like this:
public <M> IModel<M> getDefaultModel() { /* implementation here */ }
Then I could use: container.<Bar>getDefaultModel().getObject().foo()
Which I personally think is a much nicer/cleaner syntax.
The framework writers are very smart people, so I'm curious, other than the casting syntax, what differences are there in the two different definitions?
While we're on the subject, and please let me know if this should be a separate question.
Since the Generics code uses a compile time check instead of a runtime cast, would it generate slightly faster runtime code, then the explicit cast version?
There are no other differences. The difference lies purely in the syntax. With IModel<?>, the casting has to be done explicitly (as you noted). However, by using generics, you tell the compiler to cast it to Bar when returning from the getObject() method, so you don't have to cast it yourself. Other than that, the exact same thing happens in both cases.
For java versions 1.7 and earlier i guess, the compiler could not infer the type when you use a generic type in chained method calls (container.getDefaultModel().getObject()).foo()).So you have to cast it explicitly. But if you are using Java 8, I don't think you need to cast anymore. container.getDefaultModel().getObject()).foo() will work.
Read this http://openjdk.java.net/jeps/101 and this http://blog.jooq.org/2013/11/25/a-lesser-known-java-8-feature-generalized-target-type-inference/
Are there any mocking framework that can do a "full" mocking of every child in an aggregate? For example.
final Report report = createMock(Report.class);
expect(report.getReportSides().get(0).getSideGroup().get(1)).andStubReturn(createSomething());
I want this call with these indices be mocked without me having to do anything else, and before I start to write some massive testing code... is this possible in any framework, EasyMock, PowerMock, Mockito, etc?
(The class example is a legacy class auto-generated from a customers XML, hence the weird class structure, and the absence of domain service layer).
I'm sure you know it's strongly advised to not mock values, but with legacy stuff there could be funky stuff.
Anyway the following declaration might do a great part of the job:
mock(Report.class, RETURNS_DEEP_STUBS)
However you seem to have collections in your aggregate report.getReportSides().get(0).getSideGroup().get(1), and due to type generics erasure Mockito or others frameworks cannot infer the runtime type that should be in the collections, so RETURNS_DEEP_STUBS answer will create a mock matching the return type that is read through reflection, and will certainly be a mock of Object itself in the case of java collections. So you'll have to deal with it manually.
As a side note, there have been progress for generic types in mockito trunk, it can retrieve more generic information that is embedded in the class, it's clearly not near anything that have runtime introspection (impossible with current versions of Java) but it gets closer to it.
With the upgraded RETURNS_DEEP_STUBS you could do :
public interface A<K extends MyKeyType> extends Map<K, MyValueType> {}
deepStubMock.entrySet().iterator().next()
.getValue().someValueTypeMethod().eventuallyFollowedByAnotherMethod();
EDIT : looks like David answered before me in the comment :)
I'm new to Groovy (and to JMock too for that matter) and having some trouble building expectations that use matchers on the parameters of the methods being mocked. When I try to do something like this:
Expectations e = new Expectations();
e.allowing(mockObject).doSomething(Expectations.with(aNonNull(ImmutableCollection.class)))
e.will(returnValue(someResponse))
It causes the following error when building the expectation:
groovy.lang.MissingMethodException: No signature of method: static org.jmock.Expectations.with() is applicable for argument types: (org.hamcrest.core.IsNot) values: [not null]
Possible solutions: with(boolean), with(org.hamcrest.Matcher), with(byte), with(org.hamcrest.Matcher), with(char), with(org.hamcrest.Matcher)
aNonNull returns Matcher<T> (org.hamcrest.core.IsNot implements Matcher<T>) and there is an Expectations.with method that takes a Matcher so I'm not sure why Groovy is trying to find a version of with that takes the concrete class rather than the interface specified by aNonNull. I've also tried casting the return value of aNonNull to both Matcher and Matcher<T> without any change in the error. I'm not sure if there's something about the generics that's confusing Groovy or what else to check.
According to the JavaDoc, org.jmock.Expectations.with() is an instance rather than a static method. That's why you get an error.
By the way, testing/mocking frameworks built specifically for Groovy will make your life a lot easier (even when testing Java code). For example, the same expectation looks like this in Spock (http://spockframework.org):
mockObject.doSomething(_ as ImmutableCollection) >> someResponse
Another Groovy mocking framework to be aware of is GMock (http://code.google.com/p/gmock/).
We're looking at switching to Spring 3.0 and running into problems with the intersection of Spring 3.0, EasyMock, and Java Generics.
In one place, we're mocking a Spring 3.0 AbstractBeanFactory, specifically this method:
public Class<?> getType(String name) throws NoSuchBeanDefinitionException { ... }
Under earlier versions of Spring, this returns a non-generic and all was well. With the generic, however, we run into trouble with this:
expect(mockBeanFactory.getType(CLASS_NAME)).andReturn(SOME_CLASS);
Because getType returns Class<?>, andReturn requires Class<?> as a parameter, which simply doesn't work properly.
Is there a known workaround to this?
I've run into a problem like this before, with Mockito. I'm not sure why it happens yet. You can cast the expect(..) argument to the non-generic Class type, ala
expect((Class) mockBeanFactory.getType(CLASS_NAME)).andReturn(SOME_CLASS);
Then you'll just have a warning, which you can suppress if you want. Not a very elegant solution; I'm going to spend a few more minutes looking at it.
The easiest thing to avoid any casting and warnings is to use expectLastCall() instead of expect(..) (see my answer to a similar question for details).
So in this case:
mockBeanFactory.getType(CLASS_NAME);
expectLastCall().andReturn(SOME_CLASS);