2017-07-31 121 views
3

在Java中,我想写的方法测试(简单的代码片段):嘲讽的getClass()

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); 
    } 
} 

与下面的测试

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)); 
    } 
} 

的问题是,在嘲笑类Foo,foo.getClass()返回带有额外后缀的类名。事情是这样的:因为这个原因试验

Foo$$EnhancerByMockitoWithCGLIB$$45508b12 

失败,因为SOME_SET.contains(clazz所)返回

我无法嘲笑的getClass()方法上的Foo:

Mockito.when(foo.getClass()).thenReturn(Foo.class); 

由于编译器抱怨:(?类<捕获#1-延伸美孚>) 方法thenReturn在type OngoingStubbing <类< capture#1 of?延伸的Foo > >不适用的参数(<类Foo >)

问题是,怎么实现的getClass()嘲笑对象返回的值相同的getClass()真实的方法的方法(非嘲笑)对象

+0

嗯......你的问题出了什么问题。 isValid期望一个类作为它的参数。但是你在测试中传递一个对象。 –

+0

你说得对,当我简化了这个例子时,我犯了一个错误。它应该是公共布尔值isValid(Object object){return 0; SOME_SET.contains(object.getClass()); } – zoran

回答

1

简单:你不行。

请记住:a 嘲弄对象并不是真正的嘲讽类。这是东西嘲笑框架为您创建看起来像真正的类。但你不能有两种方法:要么是假的要么是真的

而在你的情况下,合理的测试看起来不一样呢:

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

@Test 
public void testIsValidForValidClass() { 
    assertThat(target.isValid(Foo.class), is(true)); 
} 

例如。在第一个地方嘲笑对象没有意义。正如你可以容易构造和通过类的对象类!

+0

我明白了。无论如何,你摇滚:) – davidxxx

+1

大声笑你真的让我笑:) – davidxxx

+0

这个答案是正确的,没有嘲笑在这里需要,但平坦的错误对象不是嘲笑类的实例。像Mockito这样的库使用代理对象来模拟(这是动态生成的子类的实例)的事实仅仅是所述库所采用的模拟实现方法的细节。其他库,如PowerMock和JMockit(我自己的)在不创建这种代理的情况下使用不同的方法。 –

2

我觉得在你的场景中嘲笑Foo是没有意义的。只需将Foo.class作为参数传递即可。您正在检查MyClass.isValid逻辑,并且您不会检查Foo上的任何交互。

+0

+1毫无疑问,最明智的答案。很多人看到人们认为他们需要使用嘲笑,当没有嘲讽的测试更好的时候... –

2

Mockito.mock(Foo.class)产生一个Foo类型的对象,但不完全是Foo类。在后台创建一个匿名代理,这是Foo的一个子类。所以,这个班是不一样的。

对于您的isValid实现的一个注意事项是:您确实想要检查该类,还是仅检查该类的类型(也将接受子类isAssignableFrom)。如果你检查类型匹配,那么你可以用模拟类来测试你的方法。

另外,你认为你可以以某种方式处理对象而不是类(例如isValid(object))吗?在我看来,使用对象在OOP中比在clazz中更好。 我建议:

public boolean isValid(Object obj) { 
     return SOME_SET.stream().anyMatch(clazz -> clazz.isInstance(obj)); 
    } 
0

当初始化对象“富”,只是创建Foo类型的对象,而不是创建美孚的一个模拟的。例如,如果可能的话:

Foo foo = new Foo() 
+0

如果可能的话,这会很好,但是在现实生活中,Foo是GWT小部件,不可能是在测试中实例化,所以在测试中使用它的唯一方法是创建一个模拟。 – zoran