Closed GoogleCodeExporter closed 9 years ago
What do you think of issue 290 on that matter ?
The fact is, it's not that difficult to add this feature, but we have to be
careful with the API, we are not an injection framework. The proposed
annotation name @Collaborator has an interesting meaning, in the sense that it
does not make people think of it as DI.
So you *might* be able to write that :
@RunWith(MockitoJUnitRunner.class)
public class SomeTest {
@InjectMocks Echoer echoer;
@Collaborator Observer theObserver = makeObserver();
private Observer makeObserver() {
Observer mock = mock(Observer.class);
doThrow(Exception.class).when(mock).update(any(Observable.class), any());
return mock;
}
@Test(expected = Exception.class) public void name() {
echoer.echo("yay");
}
private static class Echoer extends Observable {
private Echoer(Observer observer) { this.addObserver(observer); }
public void echo(String msg) {
setChanged();
notifyObservers(msg);
}
}
}
Original comment by brice.du...@gmail.com
on 1 Mar 2012 at 11:56
just a few comments on http://code.google.com/p/mockito/issues/detail?id=290
1) This is indeed exactly the same issue, so close this one as a 'duplicate'
2) in the comments of issue 290, someone is talking about studying how to do
it... but in my issue, I actually gave a patch as an attachment that does it!
try the patch, it is few lines of code...
3) I don't like the class name "Collaborator", and I find "CustomMock" more
appropriate and more intuitive. Is it only for my way of programming ? Let me
explain why I prefer this name:
- "Collaborator" has no special meaning. It means someone working with another, but not by pleasure (this was the name gave to the few french people working with german enemies during world war 2)...
- "CustomMock" means that the annoted object is considered as a "mock", and more specifically is a "custom" "mock". Just like in java naming convention, a BufferedOutputStream is a "stream", for "output", using "buffer" ... always read for right to left to say what it is, and what it does.
- So @InjectMocks is naturally able to inject "Mock", all kinds of mocks: "Mock", "CustomMock", and "AnyOtherMock".
- I would even consider more intuitive to have "Spy" annotation class beeing renamed "SpyMock"... because just as here, a "SpyMock" object is considered a "Mock" for dependency (@InjectMocks), that internally use "Spy" stubbing.
- By having a naming convention (namespace) for all annotations to always prefix or suffix by "Mock", it is more easy to remember the mockito annotation names, and the fact that theses classes are from Mockito package. In spring Roo for example, you have such a convention: all annotations starts with @Roo.
4) Last but not least remarks...
I have found another solution since yesterday for injecting my dependency
objects, that use both Spring and Mockito, and I find that it is also an
elegant way of mixing test concerns with spring for the integration test part
(using real DAO), and mockito for the specific test part. As You said, Mockito
is not a dependency framework, so let's use spring for what it really does
well..
You might add this sample in the wiki web site.
Here is my test:
// almost all my tests in mymodule inherits from this Junit spring settings
@RunWith(SpringJUnit4Runner.class)
@ContextLocation("classpath:/mymodule-applicationContext-junit.xml")
public class SpringBaseTestCase extends Assert {
@Autowired private ApplicationContext testApplicationContext;
protected void autowireBeanForSpringTest(Object testObj) {
testApplicationContext.getAutowireCapableBeanFactory().autowireBean(testObj);
}
}
public class XyzTest extends SpringBaseTestCase {
@InjectMocks
protected XyzService sut;
@Mock
protected Dependency1 dep1;
@Spy
protected Dependency2 dep2 = new Dependency2Impl();
@CustomMock
protected Dependency3 dep3 = new Dependency3Impl();
@Before public void setup() {
//step 1: create the system under test (the object is local to the test, not created by spring or mockito)
sut = new XyzServiceImpl();
// step 2: autowire using spring the object annoted dependencies, but using beans from the spring junit xml context (not the real production xml context)
autowireBeanForSpringTest(this);
// step 3: overwrite some of the sut dependencies with mockito mocks, created by @Mock,@Spy,@CustomMock
MockitoAnnotations.initMocks(this);
// step 4: manually overwrite some of the sut settings if ever
sut.setXyzMode(true);
sut.setXyzSetting(1234);
}
}
Original comment by arnaud.n...@gmail.com
on 1 Mar 2012 at 8:07
Hi Arnaud,
On point 2: you should read "...studying how to do it (properly and API-wise)"
;)
Because I agree there is now real difficulty to change some line of code here
and there, but imagine someone want his own other annotation, then what... we
clearly can't do that forever.
On point 3: I disagree with you, because @Collaborator wasn't intended for
mocks at first and because @CustomMock semantic could mean mocks customized by
other means than Mockito, even non Mockito mocks. This question is the real
"study on how to do it" ;)
On point 4: It works, but I'm still not fond of this CustomMock and Spring
autowiring, due to the nature of the test, maybe I need some time to appreciate
the idea.
Original comment by brice.du...@gmail.com
on 1 Mar 2012 at 11:30
I agree with Brice, the CustomMock name is not accurate because: 1. it may not
be a mock at all, 2. 'custom' is confusing as mockito does not have a notion of
'custom' mock so it reads to me as some kind of mock from a different mocking
tool that is adapted to mockito.
We may still iterate and brainstorm on a good name but so far Collaborator >
CustomMock :)
Original comment by szcze...@gmail.com
on 12 Mar 2012 at 2:40
Oh by the way I did a typo error in my above comment on point 2
=> I agree there is *no* real difficulty ...
Original comment by brice.du...@gmail.com
on 12 Mar 2012 at 3:32
Original comment by brice.du...@gmail.com
on 3 Sep 2012 at 10:00
Original issue reported on code.google.com by
arnaud.n...@gmail.com
on 29 Feb 2012 at 9:47Attachments: