How to mock a generic parameter for a unit test in Java?
You are passing wrong parameters to when
. It may be a bit confusing, but there are two different usages of when
method (actually those are two different methods):
when(mockedObject.methodYouWantToMock(expectedParameter, orYourMatcher)).thenReturn(objectToReturn);
doReturn(objectToReturn).when(mockedObject).methodYouWantToMock(expectedParameter, orYourMatcher);
Note: pay attention to input parameters of when
method in both cases.
In your particular case you could do something like this:
doReturn(null).when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));
This will fix your compilation issues. However the test will fail at runtime with org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue
because you are trying to return something from a void
method (null
is not void
). What you should do is :
doNothing().when(iGenericServiceMock).save(any(Theodore.class), any(AnotherClass.class));
Later you can check the interactions with your mock using verify
method.
UPDATE:
Check your imports. You should use org.mockito.Matchers.any
instead of org.hamcrest.Matchers.any
.
Unable to mock a method with generic parameters
Mockito.any() is not applicable for the type Class in your case. Should be fine if you specify Mockito.any(Class.class) in your condition.
public class TestClass
{
public class MyClass
{
public <K, T> T test(String s, K obj, final Class<T> clazz)
{
return null;
}
}
@Test
public void test()
{
MyClass myClass = Mockito.mock(MyClass.class);
Mockito.when(myClass.test(Mockito.anyString(), Mockito.any(), Mockito.any(Class.class))).thenThrow(new IllegalArgumentException());
myClass.test(null, null, null);
}
}
Using Mockito to mock classes with generic parameters
I think you do need to cast it, but it shouldn't be too bad:
Foo<Bar> mockFoo = (Foo<Bar>) mock(Foo.class);
when(mockFoo.getValue()).thenReturn(new Bar());
Mockito mocking when() for two generic methods of different types
Mockito doesn't know which generics was specified in front of any()
invocation and anyway it doesn't matter.
The parameters expected in the recording a mock behavior has to rely on :
- value (in terms of
equals()
- or in terms of captor if
equals()
is not adequate - or
any()
if the value of the parameter in the mock invocation doesn't matter or is not known in the test fixture
These never have to rely on the generic specified on.
To have a good example, look at Mockito.anyCollectionOf(Class<T> clazz)
or Mockito.anyMapOf(Class<K> keyClazz, Class<V> valueClazz)
.
These methods know the class passed but anyway, their specifications state :
This method don't do any type checks, it is only there to avoid
casting in your code. This might however change (type checks could be
added) in a future major release.
Generally what you want to check is that the method to mock was invoked with the expected parameter and not any parameter : so any()
will never achieve it.
So trying to check only the generic type but accepting any values as parameters seems be an anti pattern mocking.
In your case, if equals()
is not convenient for the matching in the when()
recording, use Mockito captor with verify()
and do the check after the execution of the mock.
How to mock a generic implementation of a protocol?
The
Store<Student>
syntax has never been supported, but there has been a lot of talk on the Swift forum about it lately—it may be soon.There are many other Q/A's on Stack Overflow about not being able to use a protocol with an associated type like an existential—it's finally available but only in Xcode 13.3 (beta).
It seems to me that you want things constrained like this:
class MyClassToBeTested<BookStore: Store, StudentStore: Store>
where
BookStore.AnyData == Book,
StudentStore.AnyData == Student
{
let bookStore: BookStore
let studentStore: StudentStore
If not, the latest syntax, available starting in Xcode 13.3, is
class MyClassToBeTested<StudentStore: Store>
where StudentStore.AnyData == Student {
let bookStore: any Store
let studentStore: StudentStore
init(
bookStore: any Store,
studentStore: StudentStore
) {
self.bookStore = bookStore
self.studentStore = studentStore
}
}
Related Topics
Java.Lang.Noclassdeffounderror: Org/Springframework/Core/Env/Configurableenvironment
Java.Lang.Noclassdeffounderror: Lorg/Apache/Logging/Log4J/Logger; But the Artifact Exists
Correct Way to Focus an Element in Selenium Webdriver Using Java
Http 415 Unsupported Media Type Error With Json
Jpa- Joining Two Tables in Non-Entity Class
In Java, How to Determine If a Char Array Contains a Particular Character
How to Have Each Record of Json on a Separate Line
How to Use Jackson to Deserialise an Array of Objects
How to Increase the Java Heap Size Permanently
Jackson @Jsonproperty Not Working If Property Name Not Equal Field Name
Javax.Validation - Allow Null But Validate If the Value Is Not
Spring Boot - Post Method Not Allowed, But Get Works
Java: How to Ask User If He/She Wants to Continue Program
Remove Duplicate Values from Hashmap in Java
Java.Sql.Sqlexception: Access Denied for User 'Root'@'Localhost' (Using Password: Yes)
How to Pass or Send Data from Recyclerview Adapter to Fragment
Mock Objects Created Inside Method Under Test to Verify the Arguments Passed
How to Take Input as String With Spaces in Java Using Scanner