Я сталкиваюсь с проблемой ниже, когда при косвенном обновлении полей на шпионском объекте шпион НЕ видит обновлений в примитивных полях, тогда как он видит ссылку один раз.
В качестве примера:
import org.junit.Test;
import org.mockito.Mockito;
import java.util.function.Consumer;
import java.util.concurrent.atomic.AtomicBoolean;
public class MyTest {
class Actor {
Consumer<Boolean> consumer;
void init(Consumer<Boolean> consumer){
this.consumer = consumer;
}
void act(boolean flag){
this.consumer.apply(flag);
}
}
class TestClass {
boolean field = true;
AtomicBoolean refField = new AtomicBoolean(true);
TestClass(Actor actor){
actor.init( flag -> {
System.out.println("Changing field to " + flag);
field = flag;
refField.set(flag);
});
}
void call(){
this.doSomething(field);
}
void callRef(){
this.doSomething(refField.get());
}
void doSomething(boolean flag){
System.out.println("#doSomething(" + flag + ")");
}
}
@Test
public void test(){
// given an actor and a spied TestClass
Actor actor = new Actor();
TestClass spy = Mockito.spy(new TestClass(actor));
// when invoking the action with the primitive
spy.call();
// then expect correct invocation
Mockito.verify(spy, Mockito.times(1)).doSomething( true );
// when invoking the action with the ref field
spy.callRef();
// then expect correct invocation
Mockito.verify(spy, Mockito.times(2)).doSomething( true );
// when changing the flag to 'false'
actor.act( false );
// and invoking the action with the refField
spy.callRef();
// then expect correct invocation
Mockito.verify(spy, Mockito.times(1)).doSomething(false);
// when invoking the action with the primitive
spy.call();
// then method is NOT invoked as expected !!!!!!!
Mockito.verify(spy, Mockito.times(2)).doSomething(false);
}
}
Последняя проверка не удастся, так как метод вызывается с первым примитивным значением.
Мне было интересно, почему это происходит ? Это ожидаемое поведение. Выполнение вышеуказанного теста приведет к следующему журналу:
#doSomething(true)
#doSomething(true)
Changing flag to false
#doSomething(false)
#doSomething(true)
Я ожидаю, что последний оператор журнала будет вызываться с помощью false
.
Есть какие-либо идеи по вышеизложенному?
PS: Версия = mockito-core:2.25.0