and*_*dyb 11 java type-erasure mockito java-6 java-7
使用非常简单的Mockito运行JUnit测试和类,当使用Java 1.6.0_32和Java 1.7.0_04运行测试时,我看到不同的输出,并且想要理解为什么会发生这种情况.我怀疑有一些类型的擦除正在进行,但想要一个确定的答案.
这是我的示例代码和如何从命令行运行的说明:
import org.junit.*;
import org.junit.runner.*;
import org.mockito.*;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.*;
import java.util.*;
@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
@Mock Map<String, String> mockStringString;
@Mock Map<String, Integer> mockStringInteger;
@InjectMocks FooService fooService;
public static void main(String[] args) {
new JUnitCore().run(FooServiceTest.class);
}
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void checkInjection() {
when(mockStringString.get("foo")).thenReturn("bar");
fooService.println();
}
}
Run Code Online (Sandbox Code Playgroud)
import java.util.*;
public class FooService {
private Map<String, String> stringString = new HashMap<String, String>();
private Map<String, Integer> stringInteger = new HashMap<String, Integer>();
public void println() {
System.out.println(stringString.get("foo") + " " + stringInteger);
}
}
Run Code Online (Sandbox Code Playgroud)
要编译并运行此示例:
javac -cp junit-4.10.jar;mockito-all-1.9.0.jar *.javajava -cp .;junit-4.10.jar;mockito-all-1.9.0.jar FooServiceTest我相信上面的输出是null {}因为@InjectMocks字段注入无法正确解析类型,因为它们都是Map类型.这是对的吗?
现在更改其中一个模拟名称以匹配类中的字段应该允许Mockito找到匹配项.例如改变
@Mock Map<String, Integer> mockStringInteger;
Run Code Online (Sandbox Code Playgroud)
至
@Mock Map<String, Integer> stringInteger;
Run Code Online (Sandbox Code Playgroud)
然后用Java 1.6.0_32编译/运行给出(IMHO预期的)输出bar stringInteger但是1.7.0_04给出null stringInteger.
以下是我如何运行它(从Windows 7中的命令行):
E:\src\mockito-test>set PATH="C:\Program Files (x86)\Java\jdk1.6.0_32\bin"
E:\src\mockito-test>javac -cp junit-4.10.jar;mockito-all-1.9.0.jar *.java
E:\src\mockito-test>java -cp .;junit-4.10.jar;mockito-all-1.9.0.jar FooServiceTest
bar stringInteger
E:\src\mockito-test>set PATH="C:\Program Files (x86)\Java\jdk1.7.0_04\bin"
E:\src\mockito-test>javac -cp junit-4.10.jar;mockito-all-1.9.0.jar *.java
E:\src\mockito-test>java -cp .;junit-4.10.jar;mockito-all-1.9.0.jar FooServiceTest
null stringInteger
Run Code Online (Sandbox Code Playgroud)
我相信上面的输出是I null {},因为@InjectMocks字段注入无法正确解析类型,因为它们都是Map类型.它是否正确?
是的,在这些领域正确Mockito无法消除歧义,所以它只是忽略了这些模糊的领域.
使用非常简单的Mockito运行JUnit测试和类,当使用Java 1.6.0_32和Java 1.7.0_04运行测试时,我看到不同的输出,并且想要理解为什么会发生这种情况.
实际上,差异在于Arrays.sort的不同行为,因此在JDK 6和JDK 7之间存在Collections.sort().差异在于新的算法,它应该执行少于掉期20%的交换.这可能是这个交换操作使得JDK6和JDK7下的工作.
如果你只重命名具有相同类型(或相同擦除)的字段的一个模拟字段,那么我可能正在"寻找麻烦".当模拟不能按类型区分时,你真的应该将所有模拟字段命名为相应的字段,但Javadoc并没有明确说明.
非常感谢报告这种奇怪的行为,我在Mockito上创建了一个问题,但是现在我不会真正解决这个问题,而是确保JDK中的相同行为.解决这种情况可能需要在保持兼容性的同时编写新的algorythm,同时您应该将所有的场模拟命名为测试类的字段.
目前要做的事情可能是通过额外的比较来调整比较器,以在JDK6和JDK7上强制执行相同的顺序.另外在Javadoc中添加了一些警告.
编辑:两次通过可能会解决大多数人的问题.
希望有所帮助.感谢您发现问题.
另外,无论是你需要的MockitoAnnotations.initMocks(this);还是跑步者@RunWith(MockitoJUnitRunner.class),都不需要使用两者,甚至可能会引起一些问题.:)
| 归档时间: |
|
| 查看次数: |
4040 次 |
| 最近记录: |