I have a code like mRestAccess.exchange(url, HttpMethod.GET, request, byte[].class); Now I want to test this using JUnit.
When I am writing Mockito.doReturn(stringResponse).when(mRestAccess).exchange(Mockito.anyString(), Mockito.any(HttpMethod.class), Mockito.any(HttpEntity.class),???????);
What to write in place of ????????
You can use Mockito.eq to test argument equality (using equals). For even more flexibility, any(Class.class) would work, but may not constrain the type parameter T enough to work for some Mockito syntax.
Mockito.doReturn(stringResponse)
.when(mRestAccess)
.exchange(
Mockito.anyString(),
Mockito.any(HttpMethod.class),
Mockito.any(HttpEntity.class),
Mockito.eq(byte[].class));
I had a similar use case with Spring's RestClient, exchange method, which asks for:
restClient.exchange(URI, HttpMethod, HttpEntity, String.class)
I solved it with:
ArgumentCaptor<URI> uriCaptor = ArgumentCaptor.forClass(URI.class);
ArgumentCaptor<HttpEntity> entityCaptor = ArgumentCaptor.forClass(HttpEntity.class);
ArgumentCaptor<HttpMethod> methodCaptor = ArgumentCaptor.forClass(HttpMethod.class);
verify(restTemplate, times(1)).exchange(
uriCaptor.capture(),
methodCaptor.capture(),
entityCaptor.capture(),
Mockito.eq(String.class));
Then you get the chance to inspect the values as well, besides intercepting the call.
You can also do, for example:
doReturn(new ResponseEntity<String>("it works...", 200))
.when(restTemplate).exchange(
ArgumentMatchers.eq(uri),
ArgumentMatchers.eq(HttpMethod.GET),
ArgumentMatchers.eq(httpEntity),
Mockito.eq(String.class)
);
Use below statement to mock spring restTemplate using powermockito.
PowerMockito.when(restTemplate.exchange(
Matchers.anyString(),
Matchers.any(HttpMethod.class),
Matchers.<HttpEntity<?>> any(),
Matchers.any(Class.class)))
.thenReturn(respEntity);
Refer this link for detailed explanation.
Related
Dependencies used:
implementation("org.jooq:jooq:3.17.2")
implementation("org.jooq:jooq-meta:3.17.2")
implementation("org.jooq:jooq-kotlin-coroutines:3.17.2")
implementation("org.jooq:jooq-kotlin:3.17.2")
runtimeOnly("io.r2dbc:r2dbc-spi") {
version { strictly("0.9.1.RELEASE") }
}
runtimeOnly("dev.miku:r2dbc-mysql:0.8.2.RELEASE")
runtimeOnly("io.r2dbc:r2dbc-pool:0.9.1.RELEASE")
// Kotlin 1.6.20
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8")
Using R2DBC DSL configuration:
private val dsl = DSL.using(
ConnectionFactories.get(
ConnectionFactoryOptions
.parse("r2dbc:pool:mysql://localhost:3303/db")
.mutate()
.option(ConnectionFactoryOptions.USER, databaseUser)
.option(ConnectionFactoryOptions.PASSWORD, databasePassword)
.build()
)
)
Running on JDK17:
DSL.using(dsl.configuration()).insertInto(table)
.set(fromDomain(item)).apply(builder)
.executeAsync()
.await()
throws an error on line with .await()
Attempt to execute a blocking method (e.g. Query.execute() or ResultQuery.fetch()) when only an R2BDC ConnectionFactory was configured. jOOQ's RowCountQuery and ResultQuery extend Publisher, which allows for reactive streams implementations to subscribe to the results of a jOOQ query. Simply embed your query in the stream, e.g. using Flux.from(query). See also: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/reactive-fetching/
org.jooq.exception.DetachedException: Attempt to execute a blocking method (e.g. Query.execute() or ResultQuery.fetch()) when only an R2BDC ConnectionFactory was configured. jOOQ's RowCountQuery and ResultQuery extend Publisher, which allows for reactive streams implementations to subscribe to the results of a jOOQ query. Simply embed your query in the stream, e.g. using Flux.from(query). See also: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/reactive-fetching/
(Coroutine boundary)
at ...
Caused by: org.jooq.exception.DetachedException: Attempt to execute a blocking method (e.g. Query.execute() or ResultQuery.fetch()) when only an R2BDC ConnectionFactory was configured. jOOQ's RowCountQuery and ResultQuery extend Publisher, which allows for reactive streams implementations to subscribe to the results of a jOOQ query. Simply embed your query in the stream, e.g. using Flux.from(query). See also: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/reactive-fetching/
at org.jooq_3.17.2.MYSQL.debug(Unknown Source)
at app//org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:300)
at app//org.jooq.impl.Tools$3$1.block(Tools.java:5803)
at java.base#17.0.1/java.util.concurrent.ForkJoinPool.compensatedBlock(ForkJoinPool.java:3449)
at java.base#17.0.1/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3432)
at app//org.jooq.impl.Tools$3.get(Tools.java:5800)
at java.base#17.0.1/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1768)
at java.base#17.0.1/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1760)
at java.base#17.0.1/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base#17.0.1/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
at java.base#17.0.1/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
at java.base#17.0.1/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
at java.base#17.0.1/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
although executeAsync is used instead of execute. I would not expect this error and would expect the query to run successfully. Thanks for any help in trying to solve this issue.
I believe I understand it now. Instead of .executeAsync().await() I can use .awaitLast() and instead of fetchAsync() I can use .asFlow().toList()
There's a known limitation (as of jOOQ 3.17) that jOOQ doesn't execute fetchAsync() and other CompletionStage producing API calls via R2DBC yet, see: https://github.com/jOOQ/jOOQ/issues/13590
But since you're using kotlin coroutines as a "frontend" of jOOQ reactive queries, just use the recommended bridge module:
<dependency>
<groupId>org.jooq</groupId>
<artifactId>jooq-kotlin-coroutines</artifactId>
</dependency>
It allows you to use jOOQ like this, for example:
fun coroutinesWithTransactions() {
val actor: ActorRecord = runBlocking {
insertActorTransaction()
}
println(actor)
}
suspend fun insertActorTransaction(): ActorRecord {
return ctx.transactionCoroutine(::insertActor)
}
suspend fun insertActor(c: Configuration): ActorRecord = c.dsl()
.insertInto(ACTOR)
.columns(ACTOR.ACTOR_ID, ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
.values(201L, "A", "A")
.returning()
.awaitFirst()
See also:
https://blog.jooq.org/3-17-0-release-with-computed-columns-audit-columns-pattern-matching-reactive-transactions-and-kotlin-coroutine-support/
I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.
MyClass is an interface and myInstance is an implementation of that, if that matters.
What do I need to do to correct this spying behaviour?
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.
My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package
package common;
public class AnimalĀ {
void packageProtected();
}
package instances;
class Dog extends Animal { }
and the test classes
package common;
public abstract class AnimalTest<T extends Animal> {
#Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
#Test
public void myTest(){}
}
The compilation is correct, but when it tries to setup the test, it invokes the real method instead.
Declaring the method protected or public fixes the issue, tho it's not a clean solution.
The answer by Tomasz Nurkiewicz appears not to tell the whole story!
NB Mockito version: 1.10.19.
I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.
The method in question here, getContentStringValue, is NOT final and NOT static.
This line does call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
This line does not call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.
Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?
Anyway:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...
But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...
* is "generic parameter" the right term?
One more possible scenario which may causing issues with spies is when you're testing spring beans (with spring test framework) or some other framework that is proxing your objects during test.
Example
#Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
In above code both Spring and Mockito will try to proxy your MonitoringDocumentsRepository object, but Spring will be first, which will cause real call of findMonitoringDocuments method. If we debug our code just after putting a spy on repository object it will look like this inside debugger:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
#SpyBean to the rescue
If instead #Autowired annotation we use #SpyBean annotation, we will solve above problem, the SpyBean annotation will also inject repository object but it will be firstly proxied by Mockito and will look like this inside debugger
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
and here is the code:
#SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
Important gotcha on spying real objects
When stubbing a method using spies , please use doReturn() family of methods.
when(Object) would result in calling the actual method that can throw exceptions.
List spy = spy(new LinkedList());
//Incorrect , spy.get() will throw IndexOutOfBoundsException
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I've found yet another reason for spy to call the original method.
Someone had the idea to mock a final class, and found about MockMaker:
As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline
Source: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods
After I merged and brought that file to my machine, my tests failed.
I just had to remove the line (or the file), and spy() worked.
One way to make sure a method from a class is not called is to override the method with a dummy.
WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
#Override
public void select(TreeItem i) {
log.debug("SELECT");
};
});
As mentioned in some of the comments, my method was "static" (though being called on by an instance of the class)
public class A {
static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static
Work around was make an instance method or upgrade Mockito to a newer version with some config: https://stackoverflow.com/a/62860455/32453
Bit late to the party but above solutions did not work for me , so sharing my 0.02$
Mokcito version: 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
Following did NOT work for me (actual method was being called):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
Following WORKED:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());
I have a test that doesn't fail when it should:
import static org.assertj.core.api.Assertions.assertThat;
#Test
public void testTransactionResponse() {
String id= "004";
long amount= 5000001L;
TransactionResource transactionResource = buildTransactionResource(amount, "EUR");
System.out.println(transactionController.create(id, transactionResource).getStatusCode()); //the output is 403
assertThat(transactionController.create(id, transactionResource).getStatusCode().equals(200)); //is true and test doesn't fail
}
How is it possible?
assertThat returns BooleanAssert and doesn't actually assert anything.
AssertJ provides fluent API so you're expected to call assert methods after that:
assertThat(
transactionController.create(id, transactionResource).getStatusCode().equals(200)
).isTrue();
But it doesn't seem that you need AssertJ for that. JUnit's own assertTrue would suffice:
assertTrue(transactionController.create(id, transactionResource).getStatusCode().equals(200));
or even better, assertEquals:
assertEquals(200, transactionController.create(id, transactionResource).getStatusCode());
I would use:
assertThat(operation.getStatusCode()).isEqualTo(200);
As #default locale stated, it is true that assertThat(false) does not check anything, you can detect this bad usage with findbugs as explained here http://joel-costigliola.github.io/assertj/assertj-core.html#faq-incorrect-api-usage.
I have been recently using Hamcrest library to write some tests and quite successful but now I need to do something more complex and started to see a lot of difficulties. I need to inpsect and verify the properties of the items in a Map. My production code looks something like this:
Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
map.put("one", Arrays.asList(new MyItem("One")));
map.put("two", Arrays.asList(new MyItem("Two")));
map.put("three", Arrays.asList(new MyItem("Three")));
I want to write some test codes like the following, but it doesn't compile. Looks like Hamcrest's hasEntry is type-parametered, while hasItem and hasProperty only expect Object.
assertThat(map, Matchers.<String, List<MyItem>>hasEntry("one", hasItem(hasProperty("name", is("One")))));
My IDE (Eclipse) is giving this error message: The parameterized method <String, List<HamcrestTest.MyItem>>hasEntry(String, List<HamcrestTest.MyItem>) of type Matchers is not applicable for the arguments (String, Matcher<Iterable<? super Object>>). For one thing I think Eclipse is confused of which hasEntry method I wanted to use, it should be hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher) , not the hasEntry(K key, V value).
Should I just give up and get the item from the Map and manually inspect each property? Is there a cleaner way?
Youu could just use contains or containsInAnyOrder. True, you'll have to list all items in the List that way, but it works cleaner than hasItem:
#SuppressWarnings("unchecked")
#Test
public void mapTest() {
Map<String, List<MyItem>> map = new HashMap<String, List<MyItem>>();
map.put("one", asList(new MyItem("1"), new MyItem("one")));
assertThat(map, hasEntry(is("one"),
containsInAnyOrder(hasProperty("name", is("one")),
hasProperty("name", is("1")))));
}
Since #t0mppa didn't provide a good example on how to use Hamcrest's contains and containsInAnyOrder for this, here's a little something to get your started:
Map<Integer, String> columns = new HashMap<Integer, String>();
columns.put(1, "ID");
columns.put(2, "Title");
columns.put(3, "Description");
assertThat(columns.values(), contains("ID", "Title", "Description")); // passes
assertThat(columns.values(), contains("ID", "Description", "Title")); // fails
assertThat(columns.values(), containsInAnyOrder("ID", "Description", "Title")); // passes
Note that as opposed to hasItem and hasItems, these will only work if you provide them with a full list of all the values you'll be matching against. See Hamcrest's javadocs for more information.
So just to make this simpler you might try this...
assertThat((Object)map, (Matcher)Matchers.hasEntry("one", hasItem(hasProperty("name", is("One")))));
by going to a raw type you will get a warning but no compile error. If have used this trick in the past when I don't want to worry about getting all the casting just right for the compiler.
Also, you might consider using ItIterableContainingInOrder.containingInOrder(new MyItem("One"))). This will verify the entire list and if MyItem implements equals then you won't be using reflection in your tests.
the hasEntry method has two signatures:
hasEntry(key, value)
hasEntry(matcher<key>, matcher<value>)
You are using the first signature, thus you are checking whether your map contains a matcher mapped to the string "one". t0mppa's answer is using the second signature, that's why it works. The good news is you don't need to list all the elements in the list, you can just
assertThat(map, hasEntry(is("one"), hasItem(hasProperty("name", is("One")))));
I post this question and I got some explanations but I couldn't solve the problem. Now since event I have a better understanding I'm going to post this again in a new angle.
I have following lines in my node.
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
/*
* Associate the schema factory with the resource resolver, which is
* responsible for resolving the imported XSD's
*/
factory.setResourceResolver(new ResourceResolver());
Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
Schema schema = factory.newSchema(schemaFile);
Validator validator = schema.newValidator();
validator.validate(new DOMSource(document));
I think I have two options. Either to mock
Source schemaFile = new StreamSource(getClass().getClassLoader().getResourceAsStream(schemaName));
or
Schema schema = factory.newSchema(schemaFile);
I have been pulling my hair for two day to do the first one. I tried as follows
expectNew(StreamSource.class, InputStream.class).andReturn(mockSource);
and
expectNew(StreamSource.class, anyObject(InputStream.class)).andReturn(mockSource);
But didn't work.
Now I'm trying to mock the second line
Schema schema = factory.newSchema(schemaFile);
This one also not quite clear to me. Do I need to mock a factory like
SchemaFactory mockFactory = EasyMock.createMock(SchemaFactory.class);
or since factory is created using newInstance static method call is it a different way?
Appreciate any help on this problem.
Adding later
I got some lead with the situation. I have expectNew as follows.
expectNew(StreamSource.class, InputStream.class).andReturn(mockStreamSource);
When I run powermocks throws a error saying.
java.lang.AssertionError:
Unexpected constructor call javax.xml.transform.stream.StreamSource(null):
javax.xml.transform.stream.StreamSource(class java.io.InputStream): expected: 1, actual: 0
The reason is as I think getClass().getClassLoader().getResourceStream("..") return null anyway. So powermock didn't find it euqal to the initialization I describe by expectNew. How to say expect a null inputstream as parameter. I tried using just null. didn't work.
expectNew(StreamSource.class, null).andReturn(mockStreamSource);
If you're using easymock:
Extract the creation of the factory to a protected method.
protected SchemaFactory createSchemaFactory(){
return SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
}
In your test, instead of test the SUT itself create a partially mocked version of your SUT, mocking only the new method where the static invocation is done, and test it. Partial mocks using easymock.