mensahs / mockito

Automatically exported from code.google.com/p/mockito
0 stars 0 forks source link

Add annotation hints to inject other fields that are not mocks/spies #290

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Today we can writhe things like

@RunWith(MockitoJUnitRunner.class)
class SomethingTest {
  @Mock com.myapp.SomeOwnedType someType;

  @Injectmocks com.myapp.Something somethingUnderTest;
}

If Something has a property of type SomeOwedType, it will be injected by 
mockito. However if we want to follow the saying "Don't mock types you don't 
own!", and if we actually have an external dependency, say MessageSource (from 
Spring), then we have to programmatically inject this dependency. And we could 
also potentially loose the constructor injection commodity.

@RunWith(MockitoJUnitRunner.class)
class SomethingTest {
  @Mock com.myapp.SomeOwnedType someType;

  @Injectmocks com.myapp.Something somethingUnderTest;

  MessageSource messageSource = new StaticMessageSource()

  @Before public void inject_messageSource() {
    somethingUnderTest.setMessageSource(messageSource);
}

The idea is to add some hints that would allow some non-mock fields to be 
injected. We could then write something like :

@RunWith(MockitoJUnitRunner.class)
class SomethingTest {
  @Mock com.myapp.SomeOwnedType someType;

  @Injectmocks com.myapp.Something somethingUnderTest;

  @Dependency MessageSource messageSource = new StaticMessageSource()
}

Original issue reported on code.google.com by brice.du...@gmail.com on 8 Nov 2011 at 2:27

GoogleCodeExporter commented 8 years ago
Are you sure about this feature? We might be getting carried away for mocking 
tool into dependency injection :)

I'll sleep on it.

Original comment by szcze...@gmail.com on 9 Nov 2011 at 2:36

GoogleCodeExporter commented 8 years ago
Yes I'm a bit afraid of that too. However I encoutered this case, and decided 
it was worth discussing it.

Anyway this is not on my priority list, there is more important stuff to do 
before.

Original comment by brice.du...@gmail.com on 9 Nov 2011 at 2:44

GoogleCodeExporter commented 8 years ago
@InjectMocks makes our tests more concise, what makes them more readable 
(besides the fact they're now easier to write). And we really miss this 
feature, sometimes using @Spy to achieve the same effect.

Also I'd suggest to call this annotation something like @Collaborator, as such 
tests are based on interaction between collaborating objects. BTW, it would 
also sound a bit closer to testing area, not DI :).

Original comment by oleg.n.a...@gmail.com on 16 Feb 2012 at 6:45

GoogleCodeExporter commented 8 years ago
And please, increase the priority of this issue! :)

Original comment by oleg.n.a...@gmail.com on 16 Feb 2012 at 6:46

GoogleCodeExporter commented 8 years ago
I think i am growing to like the idea. :)

Original comment by szcze...@gmail.com on 16 Feb 2012 at 10:09

GoogleCodeExporter commented 8 years ago
@collaborator is a good name ! Thx.

Yeah we'll raise the priority when and especially if we decide to implement it. 
I still like this idea. But as said we don't want Mockito to be an injection 
framework, the feature shall just be an handy feature to ease working with 
mocks and their collaborators.

Original comment by brice.du...@gmail.com on 17 Feb 2012 at 10:06

GoogleCodeExporter commented 8 years ago
Maybe we need to figure out a more convenient way to hook up own annotations + 
logic. MockitoConfiguration might be too heavy duty.

Original comment by szcze...@gmail.com on 18 Feb 2012 at 10:01

GoogleCodeExporter commented 8 years ago
Mmh I don't follow you on "hooking up own annotations + logic" part, what do 
you mean by that? Having the @Collaborator does seem the right angle in regard 
of mockito and unit test, I don't see anywhere something to configure on this 
matter.

Original comment by brice.du...@gmail.com on 19 Feb 2012 at 1:50

GoogleCodeExporter commented 8 years ago
I mean that it would be cool if Mockito offered a convenient way to implement 
such feature, e.g. @Collaborator. This is where I would start developing it. 
First I would try to make mockito flexible so that implementing @Collaborator 
feature is dead simple & clean for the end user. Then I would implement 
@Collaborator directly in Mockito if desired. This way we not only support 
incoming features but also gradually make mockito more flexible.

Original comment by szcze...@gmail.com on 20 Feb 2012 at 2:01

GoogleCodeExporter commented 8 years ago
Oh ok, I agree with you.
We should make some architecture diagram of mockito and where we would like to 
go.

Original comment by brice.du...@gmail.com on 20 Feb 2012 at 2:06

GoogleCodeExporter commented 8 years ago
Issue 323 has been merged into this issue.

Original comment by brice.du...@gmail.com on 1 Mar 2012 at 11:30

GoogleCodeExporter commented 8 years ago
If we want to further improve the InjectMocks capabilities I think it would be 
useful to add something like @Inject or @Collaborator. I've done a workshop 
yesterday and found that it would be very useful. I'm leaning towards @Inject 
only because @Collaborator feels like an overkill for things like an int or 
boolean field.

Original comment by szcze...@gmail.com on 22 Jun 2012 at 6:03

GoogleCodeExporter commented 8 years ago
Agreed it could be really something nice :)
However I'm against @Inject, because it might cause too much confusion with CDI 
/ JSR-330.

So you would also "inject" primitive types, that could be a nice. Though ints 
could not really be called "collaborators", they are just values.

Original comment by brice.du...@gmail.com on 23 Jun 2012 at 9:09

GoogleCodeExporter commented 8 years ago

Original comment by brice.du...@gmail.com on 3 Sep 2012 at 10:00

GoogleCodeExporter commented 8 years ago
Hello. 

Is there a plan to implement this accepted enhancement? 
I find myself in the situation where I would like to inject a Java 8 Clock 
instance returned by Clock.fixed(), but can't use @Spy because the returned 
class is final. 

This standard Clock exists precisely to help implementing tests by injecting 
fake Clock instances, but there is no way to inject them using annotations. 

Original comment by j...@ninja-squad.com on 24 May 2014 at 12:25

GoogleCodeExporter commented 8 years ago
Hi Jean-Baptiste,

Well for the moment the feature is frozen. If you have an elegant way to 
propose in a PR we can work on that.

Cheers.
Brice

Original comment by brice.du...@gmail.com on 27 Jun 2014 at 4:13

GoogleCodeExporter commented 8 years ago
Not sure what do you exactly need as 'elegant way', just a new annotation to 
mark injected dependencies. But I vote for name '@Dependency', as it is not 
necessary a collaborator. In my case I have a class with a parameter, e.g. 

class MyClass
{
   @Inject @Named("some.param")
   private int numberOfAttempts;
}

It could be quite long list of parameters which would be quite cumbersome to 
convert into constructor injection.

Original comment by kan....@gmail.com on 19 Sep 2014 at 1:54

GoogleCodeExporter commented 8 years ago
I've implemented this in an internal library and used `@Dependency`; I think 
it's quite nice.  Not entirely sure that Mockito needs to support it directly 
though.

By the way Guice 4 has a similar feature using `@Bind`: 
https://github.com/google/guice/blob/master/extensions/testlib/src/com/google/in
ject/testing/fieldbinder/BoundFieldModule.java

Original comment by tavian.b...@maluuba.com on 19 Sep 2014 at 2:43