A method where I chain optionals does not behave how I thought it would from reading the docs.
Assume all function_n return an Optional<Foo>
public Foo getFooFromService() {
return this.function_1()
.or(this.function_2())
.or(this.function_3())
.or(DEFAULT_VAL)
I thought that for the above code, if function_1 returned a non-absent Optional, then the program would return the inner value of it (the result of .get()) and not do any further computation on function_2 and function_3
My program is for sure doing that additional computation
In order to return a value from getFooFromService, function_1 and three ors have to be executed, meaning that their parameters will be evaluated. function_2 and function_3 will be run under any circumstances.
The option that might be suitable for you is the overloaded version that takes a Supplier which implies lazy evaluation.
public abstract T or(Supplier<? extends T> supplier)
UPDATE
It's a #Beta method (a subject to change), and I find it entirely useless. It resolves a Supplier<? extend T> to T, thus ruins the opportunity of building a chain. Basically, you can't rewrite your snippet to use this method.
UPDATE 1
But you could switch to Java's Optional and write
return function_1()
.orElseGet(() -> function_2()
.orElseGet(() -> function_3()
.orElse(DEFAULT_VAL)));
which isn't that expressive, but working as expected.
My formatting is awful, but you get the idea ;)
Guava "gently recommends" to use Java's Optional
So use Java's Optional to write the rather legible code:
import java.util.*;
class Main {
public static void main(String[] args) {
new Main().getFooFromService();
}
String getFooFromService() {
return this.function_1()
.or(this::function_2) // Requires Java 9
.or(this::function_3) // Requires Java 9
.orElse("DEFAULT_VALUE");
}
Optional<String> function_1() {
System.out.println("function_1 called");
return Optional.empty();
}
Optional<String> function_2() {
System.out.println("function_2 called");
return Optional.of("b");
}
Optional<String> function_3() {
System.out.println("function_3 called");
return Optional.of("c");
}
}
You'll see that in this case, with the given setup, function_1 and function_2 are called, but not function_3.
I have the following situation, where the lambda expression i used to
replace a working for loop does not work. Have no clue as to why this
fails
public class Abc implements IAbc {
// some fields
...
// field i'm interested in
#Inject #Any
private Instance<HandlerInterface> handlers;
// more members
...
// method i'm interested in
#Override
public boolean hasHandler(List<Order> orders) {
for (Order anOrder : orders) {
for (HandlerInterface aHandler : handlers) {
// following canHandler() is implemented by each
// handler that implements the HandlerInterface
if(aHandler.canHandle(anOrder)) {
return true;
}
}
return false;
}
// rest of the class content
.....
}
So I was actually trying to replace the above code, within the method,
with Lambdas (to which i'm new). The following was my replacement code
public boolean hasHandler(List<Order> orders) {
return orders.stream().anyMatch(order ->
Stream.of(handlers).map(Provider::get).anyMatch(handler ->
handler.canHandle(order)));
}
The above lambda expression fails at handler.canHandle with
AmbiguousResolutionException. I can't find out why it works with the
for loop and not with stream. Im sure im doing something wrong here -
but have no clue as to what. Any help on this is greatly appreciated.
I'm assuming Instance<HandlerInterface> implements Iterable<HandlerInterface> (or you wouldn't be able to use it in the enhanced for loop).
This means you can create a Stream of the elements of this Iterable by calling StreamSupport.stream(handlers.spliterator(), false);
So now, your method can be converted to use Streams as follows:
public boolean hasHandler(List<Order> orders) {
return orders.stream()
.anyMatch(o -> StreamSupport.stream(handlers.spliterator(), false)
.anyMatch(h -> h.canHandle(o)));
}
Note: I removed the .map(Provider::get) step, since it has no corresponding step in your original nested loop code.
In such cases create predicates starting from the innermost condition
First predicate is
if(aHandler.canHandle(anOrder)) {
return true;
}
You can write this in lambda as
private static Predicate<? super HandlerInterface> p1(Order o) {
return h -> h.canHandle(o);
}
Second(though is not very intuitive) but it is you want to check that for your order any handler that matches predicate p1, hence write that as
private static Predicate<? super Order> p2(List<HandlerInterface> handlers){
return o -> handlers.stream().anyMatch(p1(o));
}
Hence complete solution becomes
orders.stream().anyMatch(p2(handlers));
When written inline and removing braces because of single-line predicates you can re-write this as
orders.stream().anyMatch(o -> handlers.stream().anyMatch(h -> h.canHandle(o)));
I have method and need to test it:
void update() {
_cleaner.clear();
_updator.upadate();
}
The ordering of calls is important for this scenario. I want to write test like this:
void updateTest(){
Integer CLEAR = 0, UPDATE = 1;
Stack<Integer> callStack = new Stack<>();
Cleaner cleaner = mock(Cleaner.class);
Updator updator = mock(Updator.class);
when(cleaner.clear()).callback(() -> callStack.add(CLEAR));
when(updator.update()).callback(() -> callStack.add(UPDATE));
Some testingObj = new Some(cleaner, updator);
testingObj.update();
assertEquels(CLEAR, callStack.pop());
assertEquels(UPDATE, callStack.pop());
assertTrue(callStack.isEmpty());
}
_cleaner.clear() and _updator.upadate() returns void. It is clear that
when(cleaner.clear()).callback(() -> callStack.add(ClearCall));
when(updator.update()).callback(() -> callStack.add(UpdateCall));
is invalid code. What can I write except those lines for success? How to setup callback for method (with void as type of result) call by mockito?
I recommend you use the InOrder verifier to confirm that the methods are called in the order you want. See here for some of the documentation: http://site.mockito.org/mockito/docs/current/org/mockito/InOrder.html
This example is based on code straight from that documentation:
InOrder inOrder = inOrder(cleaner, updator);
inOrder.verify(cleaner).clear();
inOrder.verify(updator).update();
I've got a class like the following:
class A
{
public method doSomething()
{
//....
DAO dataAccessor = new DAO();
List<Object> result1 = dataAccessor.getData(dataAccessor.getSql1());
List<Object> result2 = dataAccessor.getData(dataAccessor.getSql2());
//.. do some stuff with the results
}
Now, I use jMockit for testing the above function, by mocking the DAO class.
This is how my test class looks like:
class A_Test
{
private A myAClass;
#Mocked DAO mockedDAO;
List<Object> resultToSql1, resultToSql2;
// ... Some initializations...
#Test
public void testDoSomething()
{
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getData(withEqual("SQL1")); result = resultToSql1;
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
};
myAClass.doSomething();
}
}
Now, it seems that the second expectation regarding getData() masks the first one, i.e. the mock object behaves as if I never declared the first lines in the expectation (the ones that handle sql1):
The first call to getData() returns empty collection, instead of the values with which I initialized resultToSql1. The second call returns resultToSql2, as expected.
If I comment the following line:
mockedDAO.getData(withEqual("SQL2")); result = resultToSql2;
the first call is returning what I defined - resultToSql1, and the second returns empty collection.
This makes sense.
So, what am I doing wrong? ?How can I define two different return values from getData() based on the parameters of the call?
Any help would be appreciated.
Thanks!
So, After digging more deeply inside the manual, I found that:
...But what if a test needs to decide the result of a recorded invocation based on the arguments it will receive at replay time? We can do it through a mockit.Delegate instance ...
So, in order to solve the above problem, the expectations block should look like this:
new NonStrictExpectations()
{
mockedDAO.getSql1(); result = "SQL1";
mockedDAO.getSql2(); result = "SQL2";
mockedDAO.getData(anyString);
result = new mockit.Delegate()
{
List<Object> getData(String sql)
{
if (sql.equals("SQL1"))
return resultToSql1;
if (sql.equals("SQL2"))
return resultToSql2;
return null;
}
}
};
This might seem like a pretty detailed question about Easymock, but I'm having a hard time finding a support site/forum/mailing list for this library.
I'm encountering a bug when using the captures() method that seems to return the captured parameters out of order.
Here's a simplified version of what I am testing:
public class CaptureTest extends TestCase {
// interface we will be mocking
interface Processor {
void process(String x);
}
// class that uses the interface above which will receive the mock
class Component {
private Processor processor;
private String[] s = { "one", "two", "three", "four" };
Component(Processor processor) {
this.processor = processor;
}
public void doSomething() {
for (int i = 0; i < s.length; i++) {
processor.process(s[i]);
}
}
}
public void testCapture() {
//create the mock, wire it up
Processor mockProcessor = createMock(Processor.class);
Component component = new Component(mockProcessor);
//we're going to call the process method four times
//with different arguments, and we want to capture
//the value passed to the mock so we can assert against it later
Capture<String> cap1 = new Capture<String>();
Capture<String> cap2 = new Capture<String>();
Capture<String> cap3 = new Capture<String>();
Capture<String> cap4 = new Capture<String>();
mockProcessor.process(and(isA(String.class), capture(cap1)));
mockProcessor.process(and(isA(String.class), capture(cap2)));
mockProcessor.process(and(isA(String.class), capture(cap3)));
mockProcessor.process(and(isA(String.class), capture(cap4)));
replay(mockProcessor);
component.doSomething();
//check what values were passed to the mock
assertEquals("one", cap1.getValue());
assertEquals("two", cap2.getValue());
assertEquals("three", cap3.getValue());
assertEquals("four", cap4.getValue());
verify(mockProcessor);
}
}
(Please note that this is just a simplified test case - I know that I could specify the exact value of the arguments I expect passed to my mock, but in my real case the arguments are complex objects with a handful of fields, and I want to capture the object so I can assert against just a few of those fields without re-creating the entire object in my test case).
When I run the test, it fails at:
junit.framework.ComparisonFailure: expected:<[one]> but was:<[four]>
Meaning that the parameter that EasyMock is capturing in cap1 is not the first call to the method, but the last (since the value is four). I get the same results if I reverse the captures() declarations, i.e. use cap4 with the first method call, etc.
This seems like it might be a bug within EasyMock - different parameters passed to the same method in different invocations don't seem to be capture correctly.
Is anyone else using capture() with EasyMock and having similar problems? Is there an easy workaround you know of, or a different way I can capture the parameters being passed to my mock's methods?
Update 1: fixed code sample to show I am using createMock, not createStrictMock, but I get the same error with both (although the actual value of what is captured changes).
I've received an answer on the bug I submitted to the Easymock sourceforge site, and a developer has confirmed it is indeed a bug with this version of Easymock.
It is indeed a bug. The capture is done even if it was already done. The
current workaround is to implement your own capture object and override
setValue to do this:
#Override
public void setValue(T value) {
if(!hasCaptured()) {
super.setValue(value);
}
}
I was playing around with your test and could not solve.
However I extended the Capture Class to see if the values were set in a different order (I was suspicious that EasyMock internally was using a hash with a key generated from the methods and the parameters) I was wrong the methods are set in the correct order. But there is something really weird going on.. It seems that the algorithm does some kind assigning pattern.. Well let me show the code and the strange output.... BTW the changes from mock, niceMock and strictMock didn't make anydifference..
class MyCapture extends Capture<String> {
private String id;
public MyCapture(String id) {
super();
System.out.printf("Constructor %s expecting %s\n", id, this.getClass().getName());
this.id = id;
}
private static final long serialVersionUID = 1540983654657997692L;
#Override
public void setValue(String value) {
System.out.printf("setting value %s expecting %s \n", value, id);
super.setValue(value);
}
#Override
public String getValue() {
System.out
.printf("getting value %s expecting %s \n", super.getValue(), id);
return super.getValue();
}
}
public void testCapture() {
// create the mock, wire it up
Processor mockProcessor = createStrictMock(Processor.class);
Component component = new Component(mockProcessor);
// we're going to call the process method four times
// with different arguments, and we want to capture
// the value passed to the mock so we can assert against it later
Capture<String> cap1 = new MyCapture("A");
Capture<String> cap2 = new MyCapture("B");
Capture<String> cap3 = new MyCapture("C");
Capture<String> cap4 = new MyCapture("D");
mockProcessor.process(and(isA(String.class), capture(cap1)));
mockProcessor.process(and(isA(String.class), capture(cap2)));
mockProcessor.process(and(isA(String.class), capture(cap3)));
mockProcessor.process(and(isA(String.class), capture(cap4)));
replay(mockProcessor);
component.doSomething();
// check what values were passed to the mock
assertEquals("A", cap1.getValue());
assertEquals("B", cap2.getValue());
assertEquals("C", cap3.getValue());
assertEquals("D", cap4.getValue());
verify(mockProcessor);
}
}
*And this is the output *
Constructor A expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor B expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor C expecting com.comp.core.dao.impl.CaptureTest$MyCapture
Constructor D expecting com.comp.core.dao.impl.CaptureTest$MyCapture
calling process A
setting value A expecting A
calling process B
setting value B expecting A <<Setting the wrong guy
setting value B expecting A <<Setting the wrong guy
setting value B expecting B <<Ops this is the right one..stop
calling process C
setting value C expecting B <<Setting the wrong guy
setting value C expecting B <<Setting the wrong guy
setting value C expecting C <<Setting the wrong guy
calling process D
setting value D expecting C <<Setting the wrong guy
setting value D expecting C <<Setting the wrong guy
setting value D expecting D <<Ops this is the right one..stop
getting value B expecting A
Sorry I can't help you more. It might be indeed a bug in easy mock.
You can also try using EasyMock.createNiceMock(...) instead of EasyMock.createStrictMock(...) or EasyMock.createMock(...).
Although, I agree that it looks more like a bug with createMock.
This is a problem more appropriate for state-based testing, I think.
With JMockit, you could solve it like this:
import mockit.*;
import static mockit.Mockit.*;
import mockit.integration.junit3.*;
public class CaptureTest extends JMockitTestCase
{
interface Processor { void process(String x); }
class Component
{
private final Processor processor;
private final String[] s = {"one", "two", "three", "four"};
Component(Processor processor) { this.processor = processor; }
public void doSomething()
{
for (String value : s) {
processor.process(value);
}
}
}
#MockClass(realClass = Processor.class)
static class MockProcessor
{
private final String[] expectedValues;
private int i;
MockProcessor(String... expectedValues) { this.expectedValues = expectedValues; }
#Mock
void process(String x)
{
assertEquals(expectedValues[i++], x);
}
}
public void testCapture()
{
Processor mockProcessor = setUpMock(new MockProcessor("one", "two", "three", "four"));
Component component = new Component(mockProcessor);
component.doSomething();
}
}
In short, here's what worked for me:
MyClass myMock = EasyMock.createStrictMock(MyClass.class);
...
EasyMock.checkOrder(myMock, true); // before the capture and verify, not sure if it matters
...
Capture<MyArg> capturedArgs = new Capture<MyArg>();
expect(myMock.search(capture(capturedArgs))).andReturn(someRandomReturn);
PS: I'm using EasyMock 3.0
Instead of calling EasyMock.createStrictMock(...) just call EasyMock.createMock(...). Should solve your problems.