简体   繁体   English

可以模拟System.identityHashCode吗?

[英]Is it possible to mock System.identityHashCode?

Good day. 美好的一天。

I have a tool which instruments objects in project by adding certain bytecode-generated toString implementation to each. 我有一个工具,通过向每个对象添加某些字节码生成的toString实现来检测项目中的对象。 The logic of generated toString is irrelevant but what important is that its return value depends on System.identityHashCode invocations, made inside. 生成的toString的逻辑无关紧要,但是重要的是它的返回值取决于在内部进行的System.identityHashCode调用。

Now I want to cover the generated logic with automated tests. 现在,我想用自动化测试介绍生成的逻辑。 I created a class for testing, generated toString for it and want to assert over its toString output. 我创建了一个用于测试的类,为其生成了toString ,并希望对其toString输出进行断言。 It's obvious that such test won't be reproducible, since System.identityHashCode gives different results between test runs. 显然,这种测试是不可重复的,因为System.identityHashCode在两次测试运行之间给出了不同的结果。

Is it possible somehow to mock System.identityHashCode or stabilize the result it is given? 是否有可能模拟System.identityHashCode或稳定给出的结果?

It is possible to do this using Powermock, as described here: How to Mock System.getProperty using Mockito 可以使用Powermock进行此操作,如下所述: 如何使用Mockito模拟System.getProperty

However, the better approach would be to create a class that wraps System and then inject the wrapper into the class you are trying to test. 但是,更好的方法是创建一个包装System的类,然后将包装器注入到您要测试的类中。

Then in your unit test you can inject a test implementation of the wrapper and control the output from System. 然后,在单元测试中,您可以注入包装程序的测试实现并控制System的输出。

I would introduce a testing seam: 我将介绍一个测试接缝:

@Override public String toString() {
  return toString(System.identityHashCode(object));
}

/** Visible for testing. */
String toString(int hashCode) {
  // Your implementation here.
}

This way, you can call toString(int) as many times as you want from adjacent tests without concerning yourself with PowerMock or even Mockito. 这样,您可以从相邻测试中多次调用toString(int) ,而无需考虑PowerMock甚至Mockito。

As an alternative, if System.identityHashCode is used elsewhere in your class such that results need to be consistent, you can take a replacement ToIntFunction in your constructor, and have the default implementation pass System.identityHashCode as a reference to a static method . 或者,如果在类的其他位置使用System.identityHashCode,则结果需要保持一致,则可以在构造函数中使用替代ToIntFunction ,并让默认实现将System.identityHashCode传递为对静态方法引用

public YourWrapperClass(Object object) {
  this(object, System::identityHashCode);
}

/** Visible for testing. */
YourWrapperClass(Object object, ToIntFunction<Object> hashCodeFunction) {
  this.object = object;
  this.hashCodeFunction = hashCodeFunction;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM