You could also change from unit test to integration test in case a component depends on other components, when you do that you can register your mocks as a normal service and you don't have to make changes to your code just to be able to test it.
Regards, Bram 2014-09-16 17:35 GMT+02:00 Konstantine Kougios <[email protected] >: > Setter is ok, provided the bean is visible via an interface to other > bundles. But it can create issues on bigger projects with lots of > developers. I.e. A developer can use the setter to change the field on > production code with disastrous results. Or even on test code that runs > inside the container, which means subsequent tests that use the > bean/service will fail because the service is in corrupted state. On the > other hand, the forTesting(B b) is harmless as it returns a new instance > and it’s method implies it should be used only for testing. Even if it is > used in production code, it’s side effects will be limited to the code > calling forTesting(). > > Injecting via reflection can help avoid the setter & forTesting - after > all those are only for test cases and not for production code and > reflection will only be used for testing. I am not saying it’s the best > approach, but I.e. Mockito can do that via @InjectMock and it looks pretty > tidy way of doing that and production code remains clean of testing > artifacts. > > http://docs.mockito.googlecode.com/hg/latest/org/mockito/InjectMocks.html > > Spring framework allows creation of non-mocked beans via separate > application configuration xml files, which comes handy sometimes when we > want to unit test using real objects. > > I suppose the best approach would be to use mockito, @InjectMocks when I > want to test using mocks. And forTesting() can be used when we need to > inject non-mock dependencies, for unit tests that prefer to use real > objects. > > > On 16/09/2014 16:13, "Neil Bartlett" <[email protected]> wrote: > > >Why not just create a setter method for this dependency and use that from > >the unit test? I've never understood the desire to inject directly into > >private fields. > > > >I also didn't understand your explanation about polluting state. What > >does the state matter if this is a genuine unit test? > > > >Regards, > >Neil > > > >-- > >Neil Bartlett > >Sent from a phone > > > > > >On Tuesday, 16 September 2014 at 15:31, Konstantine Kougios wrote: > > > >> I want to write a unit test which will run outside of the container. I > >> want to mock dependencies. I don’t mind about lifecycle methods as my > >> service won’t use them (or I don’t need / can mock them). > >> > >> Say for example I am writing A that uses B which downloads a big json > >>file > >> from the internet. I want to unit test it by mocking B so to avoid the > >> download: > >> > >> > >> @Service > >> Class A { > >> @Reference private B b; > >> > >> public void doSomething() { > >> V v=b.download(); > >> …. use v > >> } > >> > >> Public static A forTesting(B b){ > >> A a=new A(); > >> A.b=b; > >> Return a; > >> } > >> } > >> > >> …. And then > >> > >> Public class Atest { > >> @Test > >> Public void testDoSomething() { > >> B b=mock(B.class); > >> When(b.download()).return(“file”); > >> A a = A.forTesting(b); > >> A.doSomething…. > >> } > >> } > >> > >> Setters would be similar to the above but does felix/osgi provide a more > >> transparent way (I.e. Via reflection)? > >> > >> > >> On 16/09/2014 15:22, "David Jencks" <[email protected]> > >>wrote: > >> > >> > You don't provide enough information to know what you are doing, and I > >> > don't understand what you mean by a unit test. > >> > > >> > If you are writing a DS component and using Felix DS annotations, note > >> > that the @Reference on a field without accessors results in byte code > >> > generation of accessor methods. You might want to write them yourself. > >> > > >> > Is your "unit test" running in a DS container? > >> > > >> > If not, then you need to simulate the calls to the event > >> > (bind/updated/unbind) and lifecycle (activate/modified/deactivate) > >> > methods that the container will make in your unit test. After all the > >> > "stop" methods (deactivate and unbind) are called, the container will > >> > discard the component instance. > >> > > >> > If you are running in a DS container then register your B as a service > >> > and the container will take care of calling the (generated, with your > >> > current code)bind/unbiind methods. > >> > > >> > LIke every other component framework that accesses apparently > >>invisible > >> > members during runtime, DS calls setAccessible internally so it can > >> > access them. The spec may support field injection in the future and it > >> > will be supported using setAccssible pretty much exactly as David B. > >> > suggests. > >> > > >> > david jencks > >> > > >> > On Sep 16, 2014, at 6:59 AM, Konstantine Kougios > >> > <[email protected]> wrote: > >> > > >> > > Well, that¹s similar to the forTesting factory I mention but with > >>the > >> > > drawback that the state of A is corrupted until the JVM terminates. > >>By > >> > > corrupted I mean that my mock will be part of A until either the jvm > >> > > stops > >> > > or something else injects a different thing to A.b. If the mock is > >>set > >> > > this way while running in-container tests, A state is corrupted. > >> > > > >> > > > >> > > On 16/09/2014 14:56, "David Bosschaert" <[email protected] > > > >> > > wrote: > >> > > > >> > > > Why not set the field b in your object manually to the mock B for > >>unit > >> > > > testing? > >> > > > > >> > > > Just assign it to the field. If you insist on having it private > >>you > >> > > > can call 'Field.setAccessible(true)' in your unit test and assign > >>it > >> > > > using reflection... > >> > > > > >> > > > Best regards, > >> > > > > >> > > > David > >> > > > > >> > > > On 16 September 2014 14:39, Konstantine Kougios > >> > > > <[email protected]> wrote: > >> > > > > Hi, say I got a service A, which has a > >> > > > > > >> > > > > @Reference private B b; > >> > > > > > >> > > > > Now I want to write a unit test and mock B, how can I inject the > >> > > > > mocked > >> > > > > dependency? > >> > > > > > >> > > > > Only reasonable thing I found so far is to have a static factory > >> > > > > method > >> > > > > on A, public static A forTesting(B b) { Š } > >> > > > > > >> > > > > Thanks, > >> > > > > > >> > > > > Kostas > >> > > > > >> > > > > >>--------------------------------------------------------------------- > >> > > > To unsubscribe, e-mail: [email protected] > >> > > > For additional commands, e-mail: [email protected] > >> > > > > >> > > > >> > > > >> > > > >> > > > >>--------------------------------------------------------------------- > >> > > To unsubscribe, e-mail: [email protected] > >> > > For additional commands, e-mail: [email protected] > >> > > > >> > > >> > > >> > > >> > --------------------------------------------------------------------- > >> > To unsubscribe, e-mail: [email protected] > >> > For additional commands, e-mail: [email protected] > >> > > >> > >> > >> > >> --------------------------------------------------------------------- > >> To unsubscribe, e-mail: [email protected] > >> For additional commands, e-mail: [email protected] > >> > >> > > > > > >

