You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@felix.apache.org by Konstantine Kougios <Ko...@akqa.com> on 2014/09/16 15:39:14 UTC

testing a service, mocking dependencies

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

Re: testing a service, mocking dependencies

Posted by Dawid Loubser <da...@travellinck.com>.
The manner in which you inject dependencies in your unit test should be
exactly the same as when you deploy the component to a production
environment.

If you inject into fields in production, you should inject into fields
in your test also.
If your fields are private, and you're running DI framework that
overcomes that in production, just use the same framework in your test.
Otherwise, remove the 'private' keyword from the fields (making them
package-scope), which means your unit test can directly set them.

Private is not Private in Java (otherwise your DI framework wouldn't be
able to inject directly into them in anyway). Just don't worry about it.
Don't code objects to protect them from being hacked by other objects
deployed in the same (trusted) environment - practical security doesn't
work that way.

"Pollution of state" does not apply during object construction / setup,
only during use by clients, which should be limited to using the object
as per its interface in anyway.

Enjoy OSGi - it's lovely,
Dawid Loubser


On 16/09/2014 17:13, Neil Bartlett 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" <da...@yahoo.com.INVALID> 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
>>> <Ko...@akqa.com> 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" <da...@gmail.com>
>>>> 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
>>>>> <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
>>>>> For additional commands, e-mail: users-help@felix.apache.org
>>>>>  
>>>>  
>>>>  
>>>>  
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>>> For additional commands, e-mail: users-help@felix.apache.org
>>>>  
>>>  
>>>  
>>>  
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>>> For additional commands, e-mail: users-help@felix.apache.org
>>>  
>>  
>>  
>>  
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>  
>>  
>
>



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: testing a service, mocking dependencies

Posted by Bram Pouwelse <br...@pouwelse.com>.
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 <Konstantine.Kougios@akqa.com
>:

> 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" <nj...@gmail.com> 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" <da...@yahoo.com.INVALID>
> >>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
> >> > <Ko...@akqa.com> 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" <david.bosschaert@gmail.com
> >
> >> > > 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
> >> > > > <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
> >> > > > For additional commands, e-mail: users-help@felix.apache.org
> >> > > >
> >> > >
> >> > >
> >> > >
> >> > >
> >>---------------------------------------------------------------------
> >> > > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> >> > > For additional commands, e-mail: users-help@felix.apache.org
> >> > >
> >> >
> >> >
> >> >
> >> > ---------------------------------------------------------------------
> >> > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> >> > For additional commands, e-mail: users-help@felix.apache.org
> >> >
> >>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> >> For additional commands, e-mail: users-help@felix.apache.org
> >>
> >>
> >
> >
>
>

Re: testing a service, mocking dependencies

Posted by Konstantine Kougios <Ko...@akqa.com>.
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" <nj...@gmail.com> 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" <da...@yahoo.com.INVALID>
>>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
>> > <Ko...@akqa.com> 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" <da...@gmail.com>
>> > > 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
>> > > > <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
>> > > > For additional commands, e-mail: users-help@felix.apache.org
>> > > >  
>> > >  
>> > >  
>> > >  
>> > > 
>>---------------------------------------------------------------------
>> > > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> > > For additional commands, e-mail: users-help@felix.apache.org
>> > >  
>> >  
>> >  
>> >  
>> > ---------------------------------------------------------------------
>> > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> > For additional commands, e-mail: users-help@felix.apache.org
>> >  
>>  
>>  
>>  
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>>  
>>  
>
>


Re: testing a service, mocking dependencies

Posted by Neil Bartlett <nj...@gmail.com>.
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" <da...@yahoo.com.INVALID> 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
> > <Ko...@akqa.com> 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" <da...@gmail.com>
> > > 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
> > > > <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
> > > > For additional commands, e-mail: users-help@felix.apache.org
> > > >  
> > >  
> > >  
> > >  
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> > > For additional commands, e-mail: users-help@felix.apache.org
> > >  
> >  
> >  
> >  
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> > For additional commands, e-mail: users-help@felix.apache.org
> >  
>  
>  
>  
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
>  
>  



Re: testing a service, mocking dependencies

Posted by Konstantine Kougios <Ko...@akqa.com>.
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" <da...@yahoo.com.INVALID> 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
><Ko...@akqa.com> 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" <da...@gmail.com>
>>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
>>> <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
>>> For additional commands, e-mail: users-help@felix.apache.org
>>> 
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>> 
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
>For additional commands, e-mail: users-help@felix.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org

Re: testing a service, mocking dependencies

Posted by David Jencks <da...@yahoo.com.INVALID>.
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 <Ko...@akqa.com> 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" <da...@gmail.com> 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
>> <Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
>> For additional commands, e-mail: users-help@felix.apache.org
>> 
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
> For additional commands, e-mail: users-help@felix.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: testing a service, mocking dependencies

Posted by Konstantine Kougios <Ko...@akqa.com>.
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" <da...@gmail.com> 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
><Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
>For additional commands, e-mail: users-help@felix.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org


Re: testing a service, mocking dependencies

Posted by David Bosschaert <da...@gmail.com>.
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
<Ko...@akqa.com> 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: users-unsubscribe@felix.apache.org
For additional commands, e-mail: users-help@felix.apache.org