Export to GitHub

mockito - issue #51

allow creating a mock of multiple interfaces


Posted on Jan 28, 2009 by Massive Monkey

allow creating a mock of multiple interfaces

Comment #1

Posted on Jan 28, 2009 by Quick Panda

I would like to add that it should not just be multiple interfaces, but a class and one or more interfaces.

Comment #2

Posted on Feb 18, 2009 by Massive Monkey

Issue 59 has been merged into this issue.

Comment #3

Posted on Apr 15, 2009 by Massive Ox

Comment deleted

Comment #4

Posted on Apr 15, 2009 by Massive Ox

See discussion thread, which describes the problem. http://groups.google.com/group/mockito/browse_thread/thread/60ce44174c7dd3fe/87dab35b19c1ee16

Comment #5

Posted on Apr 21, 2009 by Massive Monkey

If someone follows this issue then we need to know how really it is useful? We'd prefer to keep Mockito API slim (please, not another overloaded mock() method!).

We're waiting for code samples with legitimate case for this feature.

Comment #6

Posted on Apr 22, 2009 by Grumpy Panda

I think this is useful. We had a usecase (also Webservices - JAXB in our case - if I remember correctly) and could not write a test with mockito for it. Is it really required to overload the mock() method? A vararg should do the trick to keep the api as is and also support multiple interfaces I think.

Comment #7

Posted on Apr 22, 2009 by Quick Panda

The problem among other things is related to generics. Consider the following methods:

public T getColoredPoint();

or

public void doHighlight(T instance);

Some might argue that you shouldn't create methods like that, but I will heartily disagree. Such method signatures add clarity and safety. Since the generics parameters can be bound by one class or interface and any number of additional interfaces, it is necessary that Mockito be able to provide the ability to mock the same constraints.

Currently, to mock any output or input for those methods, I am required to create some class that extends/implements all of the pieces of the puzzle and mock it. My code is now littered with Mock objects. It is no longer clean and straightforward.
The reason I moved to Mockito was to rid myself of these types of objects.

Comment #8

Posted on Apr 22, 2009 by Massive Monkey

Currently, to mock any output or input for those methods, I am required to create some class that extends/implements all of the pieces of the puzzle and mock it.

I don't play against those methods but they seem not to be good candidates to mock their output/input. Wouldn't you prefer to use real objects for those?

It seems that the case for multi-interface mocks is to mock method parameters / method returnables. Those objects are (following Misko Hevery's nomenclature because I like it ;) newables and it's best to use real implementations of those. I'm just hoping Mockito is not becoming a library for making it easy to create instances of objects that are difficult to create. Because for this problem there are completely different resolutions & patterns. Tell us your thoughts - does it makes sense what I'm saying?

Comment #9

Posted on Apr 23, 2009 by Quick Panda

I guess I don't understand how using the "newable" makes it easy to validate calls on the object. The point, for me, of using the mock is not in creating "difficult" objects, but in ensuring that specific things occur to the mocked object.

Comment #10

Posted on Apr 23, 2009 by Massive Monkey

Ok, could you post an example with some code that you had to manually implement an adapter where you preferred to use Mockito?

Comment #11

Posted on Apr 23, 2009 by Quick Panda

Actually, I can't, which is unfortunate. The code is question is considered proprietary and I can't release it or the tests. I can take a stab at describing the problem more fully. So here goes:

I have a set of objects that I need to design that have commonalities, but the commonalities are a mix-and-match. To tackle this problem, I created a series of "aspect" interfaces. So, class A implements I and J, while B implements J and K, and C implements I, K and L, etc. As you can see there is no clear hierarchy between these objects. True AOD might be the right answer, but that's not going to happen (politics). So the best I can do is these "aspect"-styled interfaces. What I need to test is that the various combinations are handled correctly. I could pass in mocks of the classes, but I don't know them at that point in the development, so I am currently forces to mock an abstract class that implements the combinations.

I hope that's a bit more clear. Thanks for your patience.

Comment #12

Posted on Apr 23, 2009 by Quick Kangaroo

When I have had to mock a class which implements multiple interfaces I would declare something like this among the class fields, or just above the test method:

interface Tiger extends Running, Biting {}

I could then mock it as if it were a class implementing both. The same could be done for a class implementing many interfaces, as well as to mock a concrete class implementing many interfaces e.g.:

abstract class Tiger extends Cat implements Running, Biting {}

I believe this gives all the freedom you want without any overhead, if anything it would be more readable than a varargs mock call. And if you added interfaces to the class you want to mock, you'd have to visit the test to change it anyway, so there no advantage there.

The only downside I can see would be if the base class didn't have a default constructor then you would have to provide one to match, but it should only add a little noise... but it's still a disadvantage.

Don't see any great advantage in adding the capability to Mockito... unless there's use cases I haven't come across, or disadvantages I don't see...?

Regards, Graham

Comment #13

Posted on Apr 23, 2009 by Quick Panda

I consider your Tiger examples ugly and noisy, but I respect your preference. I do something similar now; I just don't like it. ;)

As I see it, mock(A, B, C, ...) is very clear on what I am creating and testing. It happens at the time I request the mock and when I view declarations it's exactly where I need it to be. Having to find a Tiger hidden in the woods to determine exactly what it looks like adds more indirection to the test than I like.

I also believe that the assumption you have of adding an interface means changing tests is also incorrect. The current method imlpementations shouldn't change (without my knowledge and permission) when I add an interface and if I need to change the tests to cope with the additional interface they are probably testing at the wrong level.

Karl

Comment #14

Posted on Apr 23, 2009 by Quick Panda

One more thing: I think this is going to come down to where the user believes the noise is. Graham, for instance (and I hope I'm not misquoting), believes it would be noisy to have a mock(...). I believe the noise is involved in creating dummy classes to mock(Dummy).

I appreciate the time and consideration of this point. There is nothing more that I enjoy than a good archetectural debate.

Thanks,

Karl

Comment #15

Posted on Apr 23, 2009 by Quick Kangaroo

I think I went a bit too far when I said it is more readable... your point about having to look for the declaration is a good one. And the second point about 'having' to change it was maybe mis-communicated, what I meant was if (for whatever reason) you had to change a declaration to account for a new interface the same would apply to both, so neither way has anything over the other. I admit I was just spilling out ideas of how the two approaches compare ;-)

I still see one advantage, however this may also be to do with personal preference, consider if I had the call:

MyThing mockMyThing = mock(FirstInterface.class, SecondInterface.class, ThirdInterfaceWithALongName.class);

If this was happening in a few places I'd probably extract the mocking to a method of it's own, if only to save me on typing at least(!), so there's a layer of indirection there anyway, and following that is comparable to following the declaration of Tiger.class in my opinion. If it's done once in a setUp method, I would probably leave as is, but once again, it's an indirection from a particular test method.

Most of my points were that except under a few conditions* the two approaches are pretty much comparable, the difference being that manually crafting your multiple interfaces is already there in the Java language, so there's zero effort to do it that way.

Regards, Graham

  • with non-default constructors, or when there's not much typing involved, the mock(...) method is a clear winner

Comment #16

Posted on Apr 23, 2009 by Quick Kangaroo

Oh, and when I talked about 'zero effort', I of course meant that in terms of Mockito contributor effort! :)

Regards, Graham

Comment #17

Posted on Apr 25, 2009 by Massive Monkey

Hello, I see the discussion has warmed up!

Firstly, I don't vote against aspect-style interfaces. What I wanted to see is some code that requires to mock multiple interfaces because I have a feeling that we shouldn't mock them at all :)

Let me try to explain it so you can feedback. I'm going to use some of Misko Hevery's nomenclature because I think it's cool. I'm not an ardent reader of his writings - I'm just stealing the names and using it quite badly (sorry Misko).

Let's divide objects into 2 categories: injectables (services, DAOs, etc) & newables (entities, supporting objects, Strings, spam).

class SomeClass {

EmailService emailService; //injectable UserRepository userRepository; //injectable

     //newable     //newable  

public User findUser(String name) {... //newable //newable public void deleteUser(User user, Reason reason) {...

In most cases, in order to achieve highly maintainable, readable, natural code I would never mock newables. Only injectables will be mocked if necessary. The test should be able to create & use newables with ease - if it cannot then the design should be changed so that newables are easy to create & use (hint: you'll get it for free with TDD :).

Above might sound a bit dogmatic but... well... so be it :) Also, I cannot give you any proof that above bold guidelines actually make the code better - that would require sitting together on some codebase and and some experimenting. (Well, I could try to explain it but it could be a lengthy post).

Let's get to the point. From my experience with classes that implement multiple interfaces it was never required for the injectable to be mocked with multiple interfaces. Simply because injectable is a statement of dependency - the class describes that it needs exactly this type in order to work correctly. So I don't need to use multi-interface mocking for injectables. I might need it for newables, though, but those guys should not really be mocked.

I'm hungry and sleepy now and hopefully what I wrote make sense :)

Comment #18

Posted on Apr 27, 2009 by Quick Panda

Well, that's seem very well thought out, but the problem is, I am injecting these classes. My base class is a RenderingPipeline, which is a queue for adding 3D visualization tasks to the display. My aspect interfaces come into play, when I have a delegate class for interacting and controling a single aspect: RenderingPipeline & A. I may have 4 or 5 classes that extend RenderingPipeline and implemenet A. If you consider this newable, then the "right way" to test it is state-based. So, I need to check the state of RenderingPipeline & A, but that's not really possible, since it's mainly a rendering engine that produces output. I could test that the output of RenderingPipeline & A is expected but now my test covers two layers and is dependent on a specific RenderingPipeline & A implementation. I already have tests to ensure that each RenderingPipeline instance produces valid output from valid input. What I want to test is that my controller class which delegates to this pipeline is performing the correct calls with the correct parameters. I need to verify behavior, not state, since differing pipeline produce different results from the same input.

Comment #19

Posted on Apr 30, 2009 by Massive Monkey

ok, let's do it.

What about a fluent interface like:

mock(Foo.class).alsoImplement(Bar.class, Baz.class)?

Anyone can contribute a patch?

Comment #20

Posted on May 5, 2009 by Quick Panda

The fluent interface idea is interesting, but mock returns an instance of Foo, which doesn't (by default) contain an alsoImplement method. For fluency, I'd recommend adding a implementing(Class...interfaces) method and changing mock (or rather overloading mock) with: mock(Foo.class, implementing(Bar.class, Baz.class), "name");

That would add two more mock variants, one for named and unamed mocks. Possibly need an additional one for ReturnValues?

implementing() would just return a simple wrapper class used by the other classes to add the additional interfaces.

I took a quick look at the source today and I might be able to contribute something.

Karl

Comment #21

Posted on May 5, 2009 by Quick Panda

Here's a patch using my implementing() idea. I added some tests to ClassImposterizerTest and added a TODO in ClassImposterizer. Not sure how you folks would want to handle bad input at that point. I didn't add any more test as it looks like you don't test the statics when the code they rely on is tested.

Anyway, this patch should get you started.

Karl

Attachments

Comment #22

Posted on May 5, 2009 by Massive Monkey

Cool, I'll look at it. Thanks!

Comment #23

Posted on May 10, 2009 by Massive Monkey

Ok, it's checked in to trunk but I'm still working on tuning it up

Comment #24

Posted on May 12, 2009 by Massive Monkey

Ok, done in trunk. The api is as follows:

mock(Foo.class, withSettings().extraInterfaces(Bar.class));

Post here if you have better ideas on the API.

Comment #25

Posted on Jun 9, 2009 by Massive Monkey

(No comment was entered for this change.)

Status: Fixed

Labels:
Type-Enhancement Priority-Medium Milestone-Release1.8