Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
463 views
in Technique[技术] by (71.8m points)

mocking - Prevent stubbing of equals method

I would like to test my class' equals() method but Mockito seems to be calling the stub version every time. My test is as follows;

PluginResourceAdapter adapter = mock (PluginResourceAdapter.class);
PluginResourceAdapter other = mock (PluginResourceAdapter.class);

when(adapter.getNumberOfEndpointActivation()).thenReturn(1);
when(other.getNumberOfEndpointActivation()).thenReturn(0);

boolean result = adapter.equals(other);
assertFalse(result);

I know I cannot stub the equals method which means Mockito should be calling my real implementation but its not.

I have also tried this:

when (adapter.equals(any()).thenCallRealMethod()

but I get the same result.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Even beyond Mockito's limitations, it doesn't make much sense for a mocked object to use a real equals method, if for no other reason than that equals methods almost always use fields, and mocked objects never run any of their constructors or field initializers.

Also, be aware of what you're testing: In a test of Foo, ideally you should never mock Foo, even to set up a Foo to compare against. Otherwise, it's easy to inadvertently test that Mockito works, rather than testing your own component's logic.

You have a few workarounds:

  • As Garrett Hall mentioned, create real objects. This may require factoring out the "data objects" from the services that use them, and mocking the services while using real data objects. This is probably a good idea overall.

  • Create a manual mock or fake by subclassing PluginResourceAdapter or implementing the relevant interface outside of Mockito. This frees you to define all methods as needed, including equals and hashCode.

  • Create an equivalentTo method, which isn't the same as equals (and thus isn't as useful for Map or Set objects, for instance) but that has mockable semantics you can define on your own.

    This would also let you test equivalentTo freely with a mock, and simply have equals delegate to that presumably-well-tested implementation.

  • Extract an object that tests equality, and mock that. You could also use Guava's Equivalence there, or a Comparator where you test a.compareTo(b) == 0.

    class YourClass {
      class AdapterEquivalence {
        boolean adaptersAreEqual(
            PluginResourceAdapter a, PluginResourceAdapter b) {
          return a.equals(b);
        }
      }
    
      /** Visible for testing. Replace in tests. */
      AdapterEquivalence adapterEquivalence = new AdapterEquivalence();
    }
    

Note that one other potential workaround—spying on existing instances—will also redefine equals and hashCode and won't help you here.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...