¿Cómo puedo simular un método en easymock que devolverá uno de sus parámetros?


public Object doSomething(Object o); de lo que quiero burlarme. Debería devolver su parámetro. Lo intenté:

Capture<Object> copyCaptcher = new Capture<Object>();
expect(mock.doSomething(capture(copyCaptcher)))
        .andReturn(copyCatcher.getValue());

Pero sin éxito, obtengo solo un AssertionError como java.lang.AssertionError: Nothing captured yet. Alguna idea?

Author: Jitesh Upadhyay, 2010-04-19

5 answers

Estaba buscando el mismo comportamiento, y finalmente escribí lo siguiente:

import org.easymock.EasyMock;
import org.easymock.IAnswer;

/**
 * Enable a Captured argument to be answered to an Expectation.
 * For example, the Factory interface defines the following
 * <pre>
 *  CharSequence encode(final CharSequence data);
 * </pre>
 * For test purpose, we don't need to implement this method, thus it should be mocked.
 * <pre>
 * final Factory factory = mocks.createMock("factory", Factory.class);
 * final ArgumentAnswer<CharSequence> parrot = new ArgumentAnswer<CharSequence>();
 * EasyMock.expect(factory.encode(EasyMock.capture(new Capture<CharSequence>()))).andAnswer(parrot).anyTimes();
 * </pre>
 * Created on 22 juin 2010.
 * @author Remi Fouilloux
 *
 */
public class ArgumentAnswer<T> implements IAnswer<T> {

    private final int argumentOffset;

    public ArgumentAnswer() {
        this(0);
    }

    public ArgumentAnswer(int offset) {
        this.argumentOffset = offset;
    }

    /**
     * {@inheritDoc}
     */
    @SuppressWarnings("unchecked")
    public T answer() throws Throwable {
        final Object[] args = EasyMock.getCurrentArguments();
        if (args.length < (argumentOffset + 1)) {
            throw new IllegalArgumentException("There is no argument at offset " + argumentOffset);
        }
        return (T) args[argumentOffset];
    }

}

Escribí un rápido "cómo" en el javadoc de la clase.

Espero que esto ayude.

 18
Author: rems,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-17 03:18:18

Bueno, la forma más fácil sería simplemente usar la Captura en la implementación de IAnswer... al hacer esto en línea tienes que declararlo final por supuesto.

MyService mock = createMock(MyService.class);

final Capture<ParamAndReturnType> myCapture = new Capture<ParamAndReturnType>();
expect(mock.someMethod(capture(myCapture))).andAnswer(
    new IAnswer<ParamAndReturnType>() {
        @Override
        public ParamAndReturnType answer() throws Throwable {
            return myCapture.getValue();
        }
    }
);
replay(mock)

Esta es probablemente la forma más exacta, sin depender de alguna información de contexto. Esto hace el truco para mí cada vez.

 25
Author: does_the_trick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-17 16:41:16

Las capturas son para probar los valores pasados al mock después. Si solo necesita un mock para devolver un parámetro (o algún valor calculado a partir del parámetro), solo necesita implementar IAnswer.

Vea la implementación de "Remi Fouilloux"si desea una forma reutilizable de pasar el parámetro X de vuelta, pero ignore su uso de Capture en el ejemplo.

Si solo desea insertarlo como el ejemplo de "does_the_trick", de nuevo, la Captura es una pista falsa aquí. Aquí está el simplificado versión:

MyService mock = createMock(MyService.class);
expect(mock.someMethod(anyObject(), anyObject()).andAnswer(
    new IAnswer<ReturnType>() {
        @Override
        public ReturnType answer() throws Throwable {
            // you could do work here to return something different if you needed.
            return (ReturnType) EasyMock.getCurrentArguments()[0]; 
        }
    }
);
replay(mock)
 14
Author: thetoolman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-17 20:22:17

Basado en @does_the_trick y usando lambdas, ahora puede escribir lo siguiente:

MyService mock = EasyMock.createMock(MyService.class);

final Capture<ParamAndReturnType> myCapture = EasyMock.newCapture();
expect(mock.someMethod(capture(myCapture))).andAnswer(() -> myCapture.getValue());

O sin captura como @ thetoolman sugirió

expect(mock.someMethod(capture(myCapture)))
.andAnswer(() -> (ParamAndReturnType)EasyMock.getCurrentArguments()[0]);
 8
Author: Marco Baumeler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-16 21:38:17

Um, si entiendo su pregunta correctamente creo que puede ser más complicado.

Object someObject = .... ;
expect(mock.doSomething(someObject)).andReturn(someObject);

Debería funcionar bien. Recuerde que está suministrando tanto el parámetro esperado como el valor de retorno. Así que usando el mismo objeto en ambas obras.

 2
Author: drekka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-19 12:14:51