I've started using the Mockito AdditionalAnswers#returnsFirstArg, which is great:
when(myMock.myFunction(anyString())).then(returnsFirstArg());
but I was wondering if there is an easy way to extract the input argument in order to be used for example in a constructor like:
when(myMock.myFunction(anyString())).thenReturn(new MyObject((String)returnsFirstArg()));
(which obviously doesn't work...)
The easiest (only?) approach, IMHO, would be to use the thenAnswer method, which allows you to not only return a value, but actually execute some code. Java 8 makes this particularly elegant, as you could just use an anonymous lambda:
when(myMock.myFunction(anyString()))
.thenAnswer(i -> new MyObject((String)i.getArguments()[0]);
I think you maybe need a helper class AnswerPipeline that I will introduce it a moment how to make the test more readable, more expressiveness and more interesting!!!
Note: you can transform any Answer to AnswerPipeline by AnswerPipeline#will(Answer) method, not only returnsFirstArg().
THEN using syntax sugar to describe the test, for example:
Function<String, String> function = mock(Function.class);
when(function.apply(anyString())).then(
/**/ will(returnsFirstArg()) // adapt an Answer to an AnswerPipeline
/**/.as(String.class) // set the result type
/**/.to(String::toUpperCase) // transforming the result
);
assertThat(function.apply("first"), equalTo("FIRST"));
AND then it is easy to solving your problem with no difficulty:
when(myMock.myFunction(anyString()))
.then(will(returnsFirstArg()).as(String.class).to(MyObject::new));
AnswerPipeline class
interface AnswerPipeline<T> extends Answer<T> {
static <R> AnswerPipeline<R> will(Answer<R> answer) {
return answer::answer;
}
default <R> AnswerPipeline<R> as(Class<R> type) {
return to(type::cast);
}
default <R> AnswerPipeline<R> to(Function<T, R> mapper) {
return it -> mapper.apply(answer(it));
}
}
You can use thenAnswer method and create an Answer to get the argument:
when(myMock.myFunction(anyString())).thenAnswer(new Answer<MyObject>() {
#Override
public MyObject answer(InvocationOnMock invocation) throws Throwable {
String s = invocation.getArgument(0); // get first argument
return new MyObject(s);
}
});
If you're using java 8, you can use lambda syntax:
when(myMock.myFunction(anyString()))
.thenAnswer(args -> new MyObject(args.getArgument(0)));
Notes:
I didn't need to cast invocation.getArgument(0) to String, but depending on your java/mockito version, maybe it'll be necessary: (String) invocation.getArgument(0)
depending on your mockito version, the getArgument(int) method might not exist and you should use getArgumentAt(int, Class) instead (in this case, the call would be getArgumentAt(0, String.class)). Or you can use getArguments()[0] and cast it to String
Related
In Java 8 I use Optional.of(Foo).filter(FooChild.class::instance).map(FooChild.class::cast).
Is there a faster way to do in in Java 9 or newer (oneliner)?
From Java 15 and onwards, you can do the check and the cast in one operation using pattern matching with the instanceof operator. Like this:
if (foo instanceof FooChild child) {
// You can use the child variable here
}
If you don't know the target type (eg: FooChild.class), you don't have much leeway:
Optional.ofNullable(foo)
.filter(Foobar.class::instanceOf)
.map(Foobar.class::cast)
.ifPresent(foobar -> {...});
This certainly works, but if you want a one liner, you could do it yourself:
public static <T> void ifInstanceOf(Object t, Class<T> type, Consumer<T> consumer) {
if (type.isInstanceOf(t)) {
consumer.accept(type.cast(t));
}
}
And use:
ifInstanceOf(obj, Foobar.class, foobar -> {
...
});
I'm not too knowledgeable on pattern matching and Java 15 as of now, but I don't think this would work with pattern matching.
I want to filter a collection of values in Kotlin using an instance of a java.util.Predicate implementation, basically something like this:
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter(predicate)
This doesn't compile though. The following works, is that the recommended way of doing this? Feels a bit cumbersome
val predicate = JsQueryPredicate<SportEvent>(query)
schedule.sport_events.filter { predicate.test(it) }
You can use a method reference, which gets converted implicitly to a (T) -> Boolean and thus allows you to call the filter method:
schedule.sport_events.filter(predicate::test)
To answer it more directly: yes... predicate.test(it) or the nearly equivalent method reference predicate::test are the way to go... except...
If you have to deal with Java predicates more often and/or the refactoring of the Java functional types (e.g. Predicate) to Kotlin function types is planned in future, you may also want to add appropriate extension functions instead, e.g.:
fun <T> Iterable<T>.filter(predicate: Predicate<T>) = filter { predicate.test(it) }
With the following usage then:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
listOf("hello", "world")
.filter(javaPredicate)
If you replaced the Predicate in future to, e.g. (T) -> Boolean you then don't need to adapt that filter, but just replace/remove the import statement to the extension function.
Extension functions to just transform the Predicate to an appropriate Kotlin function type are possible too, but may not help you that much in future refactorings:
operator fun <T> Predicate<T>.invoke() : (T) -> Boolean = ::test
fun <T> Predicate<T>.transform() : (T) -> Boolean = ::test
Usage samples of those:
val javaPredicate : Predicate<String> = Predicate { it == "hello" }
// variant with Predicate.invoke:
listOf("hello", "world")
.filter(javaPredicate())
// variant using Predicate.transform()
listOf("hello", "world")
.filter(javaPredicate.transform())
So I recommend you the overloaded filter-method in case you plan a refactoring or otherwise just stick to filter { predicate.test(it) }/filter(predicate::test), which might make a future refactoring a bit (IDEs help ;-)) harder.
Suppose I have a library method like this (very abbreviated):
public static <V> Optional<V> doSomethingWith(Callable<V> callable) {
try {
return Optional.of(callable.call());
} catch (Exception ex) {
// Do something with ex
return Optional.empty();
}
}
And I want to something that doesn't return a value, like:
Library.</*What1*/>doSomethingWith(() -> {
foo();
return /*what2*/;
});
My first instinct for a generic method that doesn't return a value is making the type Void and returning null, however because the result gets wrapped in an Optional this would throw an exception.
What are reasonable placeholders for /*What1*/ and /*what2*/ that don't look totally random like Integer and 0?
[edit]
I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
If you need a type hint for a generic parameter that will never be used you can use Void, the JDK does this too in some cases, e.g. when converting Runnable into CompletableFuture<T> it uses Void for T.
If you use Optional.ofNullable then you can just return null for what2, which is the only valid value for Void.
[edit] I'm trying to avoid Optional.ofNullable because empty is used here to indicate that callable.call() did not complete normally.
Then you're using the wrong tool for the job. CompletionStage or CompletableFuture has the right semantics.
I usually use Boolean.TRUE to mark success, but you could return Void.class as well. Both are cheap in the sense that not every return creates a new object to be discarded. Though Class<Void> is not just Void it may serve the purpose of labelling something as void just as well.
As already mentioned you could also create your own Result-class/-enum.
Or you could of course return Optional.<Void>nothing(), too. This would result in some Optional<Optional<Void>>, but also do the trick.
If you think all of the above is ugly, I fear that the API probably isn't to well tailored to your needs. Raise an issue/pull request or look for something else.
You could also create your own type similar to Void
public class Result {
public static final Result OK = new Result();
private Result(){}
}
and then return Result.OK.
You can also enhance this type to represent also errors, if you need.
But maybe using java Void is preferable if you don't need anything special.
Use Void for the return type, which is the logical choice for "nothing", but actually return an instance of Void.
Although the javadoc for Void says it's:
...an uninstantiable placeholder class...
You can nevertheless instantiate it:
try {
Constructor<Void> c = Void.class.getDeclaredConstructor();
c.setAccessible(true);
return c.newInstance();
} catch (Exception perfunctory) {
return null; // won't happen
}
I have a stream of files that I want to filter based on the ending of the file name:
public Stream<File> getFiles(String ending) throws IOException {
return Files.walk(this.path)
.filter(Files::isRegularFile)
.map(Path::toFile)
.filter(file -> file.getName().endsWith(ending));
}
While the lambda in the last line is not bad, I thought I could use method references there as well, like so:
.filter(File::getName.endsWith(ending));
Or alternatively wrapped in parentheses. However, this fails with The target type of this expression must be a functional interface
Can you explain why this doesn't work?
Can you explain why this doesn't work?
Method references are syntactical sugar for a lambda expression. For example, the method reference File::getName is the same as (File f) -> f.getName().
Lambda expressions are "method literals" for defining the implementation of a functional interface, such as Function, Predicate, Supplier, etc.
For the compiler to know what interface you are implementing, the lambda or method reference must have a target type:
// either assigned to a variable with =
Function<File, String> f = File::getName;
// or assigned to a method parameter by passing as an argument
// (the parameter to 'map' is a Function)
...stream().map(File::getName)...
or (unusually) cast to something:
((Function<File, String>) File::getName)
Assignment context, method invocation context, and cast context can all provide target types for lambdas or method references. (In all 3 of the above cases, the target type is Function<File, String>.)
What the compiler is telling you is that your method reference does not have a target type, so it doesn't know what to do with it.
File::getName is a method reference and String::endsWith is as well. However they cannot be chained together. You could create another method to do this
public static Predicate<File> fileEndsWith(final String ending) {
return file -> file.getName().endsWith(ending);
}
and then use it
.filter(MyClass.fileEndsWith(ending))
This doesn't buy you much if you're not re-using it though.
A couple of helpers might assist in providing some semblance of what you wish for. Using the helpers below, you can replace your lambda with an expression containing method references, like this:
// since your predicate is on the result of a function call, use this to create a predicate on the result of a function
public static <A,B> Predicate<A> onResult(Function<A,B> extractor, Predicate<B> predicate){
return a -> predicate.test(extractor.apply(a));
}
// since your predicate involves an added parameter, use this to reduce the BiPredicate to a Predicate with one less parameter
public static <T,U> Predicate<T> withParam(BiPredicate<T,U> pred, U param){
return t -> pred.test(t,param);
}
public Stream<File> getFiles(String ending) throws IOException {
return Files.walk(Paths.get("."))
.filter(Files::isRegularFile)
.map(Path::toFile)
.filter(onResult(File::getName, withParam(String::endsWith, ending)));
}
Currently, I have a bunch of Java classes that implement a Processor interface, meaning they all have a processRequest(String key) method. The idea is that each class has a few (say, <10) member Strings, and each of those maps to a method in that class via the processRequest method, like so:
class FooProcessor implements Processor
{
String key1 = "abc";
String key2 = "def";
String key3 = "ghi";
// and so on...
String processRequest(String key)
{
String toReturn = null;
if (key1.equals(key)) toReturn = method1();
else if (key2.equals(key)) toReturn = method2();
else if (key3.equals(key)) toReturn = method3();
// and so on...
return toReturn;
}
String method1() { // do stuff }
String method2() { // do other stuff }
String method3() { // do other other stuff }
// and so on...
}
You get the idea.
This was working fine for me, but now I need a runtime-accessible mapping from key to function; not every function actually returns a String (some return void) and I need to dynamically access the return type (using reflection) of each function in each class that there's a key for. I already have a manager that knows about all the keys, but not the mapping from key to function.
My first instinct was to replace this mapping using if-else statements with a Map<String, Function>, like I could do in Javascript. But, Java doesn't support first-class functions so I'm out of luck there. I could probably dig up a third-party library that lets me work with first-class functions, but I haven't seen any yet, and I doubt that I need an entire new library.
I also thought of putting these String keys into an array and using reflection to invoke the methods by name, but I see two downsides to this method:
My keys would have to be named the same as the method - or be named in a particular, consistent way so that it's easy to map them to the method name.
This seems WAY slower than the if-else statements I have right now. Efficiency is something of a concern because these methods will tend to get called pretty frequently, and I want to minimize unnecessary overhead.
TL; DR: I'm looking for a clean, minimal-overhead way to map a String to some sort of a Function object that I can invoke and call (something like) getReturnType() on. I don't especially mind using a 3rd-party library if it really fits my needs. I also don't mind using reflection, though I would strongly prefer to avoid using reflection every single time I do a method lookup - maybe using some caching strategy that combines the Map with reflection.
Thoughts on a good way to get what I want? Cheers!
There aren't any first-class standalone functions, but you can do what you want with an interface. Create an interface that represents your function. For example, you might have the following:
public interface ComputeString
{
public String invoke();
}
Then you can create a Map<String,ComputeString> object like you want in the first place. Using a map will be much faster than reflection and will also give more type-safety, so I would advise the above.
While you can't have first class functions, there are anonymous classes which can be based on an interface:
interface ProcessingMethod {
String method();
}
Map<String, ProcessingMethod> methodMap = new HashMap<String, ProcessingMethod>();
methodMap.put("abc", new ProcessingMethod() {
String method() { return "xyz" }
});
methodMap.put("def", new ProcessingMethod() {
String method() { return "uvw" }
});
methodMap.get("abc").method();
Or you could use Scala :-)
Couldn't you do String to Method? Then you can cache the methods you need to execute.
This example uses an enum of named functions and an abstract FunctionAdapter to invoke functions with a variable number of homogeneous parameters without reflection. The lookup() function simply uses Enum.valueOf, but a Map might be worth it for a large number of functions.
As you've noticed, you can do what you want using the Reflection API, but you loose some benefits of the Java compiler, on top of the issues you've already come up with. Would wrapping your Strings in an object and using the Visitor pattern solve your issue? Each StringWrapper would only accept a Visitor that has the right method, or something along those lines.
Use a Map where the key is a string and the value is an object that implements an interface containing method(). That way you can get the object containing the method you want out of the map. Then just call that method on the object. For example:
class FooProcessor implements Processor{
Map<String, FooMethod> myMap;
String processRequest(String key){
FooMethod aMethod = myMap.getValue(key);
return aMethod.method();
}
}
What about Method class from the reflection API? You can find methods of a class based on name, parameters, or return type. Then you just call Method.invoke(this, parameters).
That's pretty much the same as a Map from JavaScript you are talking about.
public class CarDetailsService {
private final CarRepository carRepository;
private final Map<String, Function<CarDTO, String>> carColumnMapper = new HashMap<>();
public ApplicationDetailsServiceImpl(CarRepository carRepository) {
this.carRepository = carRepository;
//---- Initialise all the mappings ------- //
carColumnMapper.put("BRAND", CarDTO::getBrandName);
carColumnMapper.put("MILEAGE", CarDTO::getMileage);
}
public Map<String, List<CarDTO>> getListOfCars(String groupBy) {
return carRepository.findAll()
.stream()
.map(toCarDTO)
.collect(groupingBy(carColumnMapper.get(groupBy.toUpperCase())));
}
Function<CarDetails, CarDTO> toCarDTO = (carDetails) -> CarDTO
.builder()
.brand(carDetails.getBrand())
.engineCapacity(carDetails.getEngineCapacity())
.mileage(carDetails.getMileage())
.fuel(carDetails.getFuel())
.price(carDetails.getPrice())
.build();
}