Cast a mocked object throws ClassCastException - junit

I have a object which I mock using powermock while unit testing.
ClassA mockedClassA = PowerMock.createMock(ClassA.class);
Later in mycode I'm using that object with a cast. Life follows.
String hello = ((ClassB)classA).someMethod();
Junit test throws following exception at thie place.
java.lang.ClassCastException: $Proxy15 incompatible with ClassB
It looks like casting the mocked object is not possible. So how can I go through this?
I tried following thigs.
Easymock.expect((ClassB)mockedClassA.somemethod())...;
doesn't work.

Your code expects classA to be a ClassB object, but it is not (unless ClassA extends ClassB, but then you wouldn't need the cast). Have you tried
ClassA mockedClassA = PowerMock.createMock(ClassB.class)

Related

Corda query throws "com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class"

I'm developing cordapp using the example-cordapp project as a reference. I've been able to commit a transaction to the ledger and even run querias on the node to see if it's really there. However, when I try to run query from my Spring Boot application, I get this error.
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request
processing failed; nested exception is
org.springframework.http.converter.HttpMessageConversionException: JSON mapping problem:
java.util.Collections$UnmodifiableRandomAccessList[0]->net.corda.core.contracts.StateAndRef["state"]-
>net.corda.core.contracts.TransactionState["data"]-
>com.mypackage.states.MyState["party"]; nested exception is
com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class
(through reference chain: java.util.Collections$UnmodifiableRandomAccessList[0]-
>net.corda.core.contracts.StateAndRef["state"]->net.corda.core.contracts.TransactionState["data"]-
>com.mypackage.states.MyState["party"])] with root cause
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~
[na:1.8.0_251]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_251]
Here's the request code
#GetMapping(value = [ "/api/v1/states" ], produces = [MediaType.APPLICATION_JSON_VALUE])
fun getMyIOUs(): ResponseEntity<List<StateAndRef<MyState>>> {
val myStates = proxy.vaultQueryBy<MyState>().states
return ResponseEntity.ok(myStates)
}
And here's the state code
#BelongsToContract(com.sentinel.contract.SharingInformationContract::class)
class SharingInformationState(
val party: Party,
val dataOwnerId: Long,
val dataBuyerId: Long,
override val linearId: UniqueIdentifier = UniqueIdentifier()) : LinearState, QueryableState {
override val participants: List<AbstractParty> = listOf(party)
override fun generateMappedObject(schema: MappedSchema): PersistentState {
return when (schema) {
SharingInformationSchemaV1 -> SharingInformationSchemaV1.PersistentSharingInformation(
party,
dataOwnerId,
dataBuyerId,
linearId.id
)
else -> throw IllegalArgumentException("Unrecognised schema $schema")
}
}
override fun supportedSchemas(): Iterable<MappedSchema> = listOf(SharingInformationSchemaV1)
}
There's little information about this issue on the internet. Some suggest it is connected to the classpath, that something is duplicated there, but I don't know how to check. Also, this error isn't connected to the Party type. I've tried to add #JsonIgnore on a party, but then it throws on the other field. Persistence of this field in mapping schema also doesn't matter. I've tried persisting and not persisting, it changes nothing. Thanks in advance!
I believe this is because you are missing Corda Jackson support library which is required to convert Corda objects to json.
Add this to your dependencies in the build.gradle
compile "net.corda:corda-jackson:$corda_release_version"
https://github.com/corda/samples-java/blob/master/Advanced/auction-cordapp/client/build.gradle#L19
Also, make sure you have a MappingJackson2HttpMessageConverter bean configured.
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){
ObjectMapper mapper = JacksonSupport.createDefaultMapper(partyAProxy());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(mapper);
return converter;
}
https://github.com/corda/samples-java/blob/master/Advanced/auction-cordapp/client/src/main/java/net/corda/samples/client/AppConfig.java#L48
The Exception java.lang.IllegalArgumentException: object is not an instance of declaring class is something that happens if a method is called by reflection on an object which is of the wrong type.
In conjunction with jackson that may happen because a generic is lying to you. Here is an example:
class A (val x: String)
class B (val y: String)
class C (val z: List<A>)
ObjectMapper().writeValueAsString(C(listOf(B("x")) as List<A>))
This causes a compile warning, but it compiles and initially runs because of type erasure. However we forcefully injected a List<B> in a place where actually a List<A> is expected. While type erasure does remove quite a bit of information, it does not do so completely. Reflection can still be used to determine that C.z is actually of type List<A>. Jackson uses this information and tries to serialize an object of type A but instead finds an object of type B in the list and fails with the given message.
Check that your data structure actually contains the types that you expect!

Mocking Spring Data Repository

I have a BeerRepository interface that extends JPARepository<Beer,UUID>. This interface contains this method.
Page<Beer> findAllByBeerName(String beerName, Pageable pageable);
In a controller handler method, I have this.
Page<Beer> pagedResult = beerRepository.findAllByBeerName(beer.getBeerName(),
createPageRequest(0,10,Sort.Direction.DESC,"beerName"));
I am trying to unit test the controller handler method.
The #BeforeEach method is this.
. . .
Page<Beer> pagedResponse;
#BeforeEach
void setUp() {
beerList = new ArrayList<Beer>();
beerList.add(Beer.builder().build());
beerList.add(Beer.builder().build());
pagedResponse = new PageImpl(beerList);
mockMvc = MockMvcBuilders
.standaloneSetup(controller)
.build();
}
My #Test method is this.
#Test
void processFindFormReturnMany() throws Exception{
when(beerRepository.findAllByBeerName(anyString(), PageRequest.of(0,
10,Sort.Direction.DESC,"beerName"))).thenReturn(pagedResponse);
mockMvc.perform(get("/beers"))
.andExpect(status().isOk())
.andExpect(view().name("beers/beerList"))
.andExpect(model().attribute("selections", hasSize(2)));
}
On running the test, I'm getting
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
-> at
guru.sfg.brewery.web.controllers.BeerControllerTest.
processFindFormReturnMany
(BeerControllerTest.java:67)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
Any help on this will be highly appreciated.
The problem is: you cannot mix Mockito matchers with real values while mocking with when(...). See docs.
In your case the following should work correctly:
when(beerRepository.findAllByBeerName(anyString(), eq(PageRequest.of(0,
10,Sort.Direction.DESC,"beerName")))).thenReturn(pagedResponse);
or
when(beerRepository.findAllByBeerName(anyString(), any(PageRequest.class)).thenReturn(pagedResponse);
Finally, you can use the real expected string instead of anyString() and leave PageRequest.of(...) as is. It should work too (assuming that they were configured correctly).
You need to set mock class for param when you mock any method
when(beerRepository.findAllByBeerName(anyString(), any(Pageable.class)).thenReturn(pagedResponse);

Testing constructor when using #Before annotation

I want to test SomeClass methods.
For that, I need SomeClass instance in every test so I'm using #Before annotation and initiate an instance of SomeClass named SC.
The problem is:- How can I test the constructor function after I already use it? It doesn't make sense.
Additional question:- The constructor can get number of arguments and they can influnce the methods outputs, should I mock this class instead of creating an instance of it?
public class SomeClassTest {
SomeClass SC;
#Before
public void initlize() throws IOException{
SC= new SomeClass (argument1,argument2,..);
}
#Test
public void ConstructorTest() {
}
Just don't use the object SC in your ConstructorTest. If you wan't to test a certain outcome from the construction of a SomeClass object with certain parameters then just construct it as such within your ConstructorTest and then assert the relevant outcomes you expect on the newly constructed object.
And no you shouldn't be mocking this class. The test is for testing this class so if you mock it's behaviour then you aren't really testing anything.

Mockito: pass mocked object as parameter to a function (when call the function)

I am using Mockito to write a simple unit test.
I have a function to test:
public void doSomething() {
foo.getStudent(new School());
}
My test case:
#Test
public void testDoSomething() {
Foo mockedFoo = Mockito.mock(Foo.class);
School mockedSchool = Mockito.mock(School.class);
// I want to pass the mocked school as parameter when food.getStudent(school) is called
// how to pass mocked school to method?
when(mockedFoo.getStudent(???))
// run the method under test
myService.doSomething();
}
I want to pass the mockedSchool as parameter when foo.getStudent(school) is called, how to declare this in Mockito?
Seems Mockito only has when(...).thenReturn(), but is there something like when(...).thenPassArgument(mockedObject) ?
The problem lies in the way you instantiate the School class in the doSomething method; as you instantiate it on the spot you can't overload that instantiation with the mock using mockito.
If you pass it as a parameter of doSomething you should be able to perform this.
I believe PowerMock can help you if you want to overload an internal construction.
As you don't need to assert into the School instance and just pass a mocked instance as a parameter, you can do the following:
mockedBar.getStudent(Mockito.isA(School.class));
Please read the Mockito documentation about the isA(java.lang.Class<T> clazz) method.

Mocking a getter than returns an array using Mockolate

I am writing a unit test for a function that calls a getter on my object. The getter should return an array, but I get an exception thrown:
Error: No Expectation defined for Invocation:[FloxyInvocation invocationType=GETTER name="getterName" arguments=[]]
I mocked my getter with:
mock(object).getter("getterName").returns(new Array()).once();
My getter is defined in the object interface:
function get getterName():Array;
Do I need to rewrite the getter function or my mock statement?
I was mocking the interface of the object instead of and object of the class that implements the interface.