我试图使用参数化测试,我想使用Mockito.when()下面的场景。除了测试之外,我不能修改任何代码。我在引起编译错误的行上加了一条注释。我很难把它用文字表达出来,但基本上我希望能够模拟该方法,而无需在编译期间访问确切的类型。
测试类:
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Map;
import static com.example.demo.Type.A;
import static com.example.demo.Type.B;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
public class MyTest {
private static final Map<Type, Class<? extends MyStuff>> classByType = Map.of(A, StuffA.class, B, StuffB.class);
@InjectMocks
private Handler handler;
@Mock
private Converter converter;
@Mock
private Sender sender;
@Captor
private ArgumentCaptor<Thing> thingArgumentCaptor;
@ParameterizedTest
@EnumSource(value = Type.class)
void testHandle(Type type) {
MyStuff myStuff = mock(classByType.get(type));
Thing thing = mock(Thing.class);
when(myStuff.getType()).thenReturn(type);
when(converter.convert(classByType.get(type).cast(type))).thenReturn(thing); // This line is causing the compile error
handler.handle(myStuff);
verify(sender).send(thingArgumentCaptor.capture());
assertThat(thingArgumentCaptor.getValue()).isEqualTo(thing);
}
}
待测类:
public class Handler {
private final Converter converter;
private final Sender sender;
public Handler(Converter converter, Sender sender) {
this.converter = converter;
this.sender = sender;
}
public void handle(MyStuff myStuff) {
Thing thing;
switch (myStuff.getType()) {
case A:
thing = converter.convert((StuffA) myStuff);
break;
case B:
thing = converter.convert((StuffB) myStuff);
break;
default:
throw new RuntimeException();
}
sender.send(thing);
}
}
域对象:
public abstract class MyStuff {
public abstract Type getType();
}
转换器:
public interface Converter {
Thing convert(StuffA myType);
Thing convert(StuffB myType);
}
发送者:public interface Sender {
void send(Thing thing);
}
类型:
public enum Type {
A, B
}
有没有办法解决这个问题,而不写两个单独的测试方法?
您可以使用反射来调用适当的方法。尝试用以下两行替换编译错误行:
Method method = Converter.class.getMethod("convert", classByType.get(type));
when(method.invoke(converter, eq(myStuff))).thenReturn(thing);
如果在编译时不知道方法参数的类型,那么反射是唯一的方法。