模拟getClass()

zor*_*ran 6 java junit unit-testing mocking mockito

在Java中我想编写方法测试(简化代码段):

public class MyClass {
    private static final Set<Class> SOME_SET = new HashSet<Class>(Arrays.asList(Foo.class, Bar.class));

    public boolean isValid(Class clazz){
        return SOME_SET.contains(clazz);
    }
}
Run Code Online (Sandbox Code Playgroud)

以下测试的问题

import static org.mockito.Mockito.when;
import org.mockito.Mockito;

public class MyClassTest {
    @Test
    public void isValid_Foo_returnsTrue(){
        Foo foo = Mockito.mock(Foo.class);
        MyClass target = new MyClass();
        assertTrue(target.isValid(foo));
   }
}
Run Code Online (Sandbox Code Playgroud)

就是在模拟类Foo上,foo.getClass()返回带有附加后缀的类名.像这样的东西:

Foo$$EnhancerByMockitoWithCGLIB$$45508b12
Run Code Online (Sandbox Code Playgroud)

由于这个原因,测试失败,因为SOME_SET.contains(clazz)返回false.

我无法在Foo上模拟getClass()方法:

Mockito.when(foo.getClass()).thenReturn(Foo.class);
Run Code Online (Sandbox Code Playgroud)

因为编译器抱怨: 方法thenReturn(Class <capture#1-of?extends Foo>)在类型OngoingStubbing <Class <capture#1-of?extends Foo >>不适用于参数(Class <Foo>)

问题是,如何实现模拟对象的getClass()方法在真实(非模拟)对象上返回与getClass()方法相同的值

Gho*_*ica 1

很简单:你不能。

请记住:模拟对象并不是真正的模拟类。这是模拟框架为您创建的东西,让您看起来像真正的类。但你不能两全其美:要么是假的,要么是真的

在你的情况下,合理的测试无论如何看起来都是不同的:

@Test
public void testIsValidForInvalidClass() {
  assertThat(target.isValid(String.class), is(false));
}

@Test
public void testIsValidForValidClass() {
  assertThat(target.isValid(Foo.class), is(true));
}
Run Code Online (Sandbox Code Playgroud)

例如。首先模拟Class对象是没有意义的。因为您可以轻松构造和传递Class 类的真实对象!