Dmitry, I'm very confused. I use constructor injection in my services which
I always thought was the correct way to do it based on the tap docs.

I have the following test class where I'm trying to use a service.

public class TimeSheetServiceTest {

    protected static TimeSheetService timeSheetService;

    @BeforeClass
    public static void setup() {
        Registry registry;
        RegistryBuilder builder = new RegistryBuilder();
        builder.add(AppModule.class);
        registry = builder.build();
        registry.performRegistryStartup();
        timeSheetService = registry.getService(TimeSheetService.class);
    }

    @Test
    public void testService() {
        int result =
timeSheetService.getHolidayListForPayPeriod(Calendar.getInstance()).size();
        System.out.println("result " + result);
    }

}

TimeSheetService injects another service called UserInfoService userInfo
like so,

public class TimeSheetServiceImpl implements TimeSheetService {

    public TimeSheetServiceImpl(UserInfoService userInfo) {
        this.userInfo = userInfo;
    }

}

When I try running my test class, I get the following exception.

<?xml version="1.0" encoding="UTF-8"?>

<!-- Generated by org.testng.reporters.JUnitReportReporter -->
-<testsuite errors="0" time="0.000" timestamp="21 Jan 2014 19:18:58 GMT"
failures="1" tests="1"
name="org.domain.etss.services.form.TimeSheetServiceTest"
hostname="hri185169">
<!-- org.domain.etss.services.form.TimeSheetServiceTest -->
-<testcase time="0.000" name="testService"
classname="org.domain.etss.services.form.TimeSheetServiceTest">-<failure
message="Contribution
org.domain.etss.services.AppModule.contributeSecurityConfiguration(Configuration,
SecurityFilterChainFactory) (at AppModule.java:312) is for service
'SecurityConfiguration', which does not exist."
type="java.lang.IllegalArgumentException">
<![CDATA[java.lang.IllegalArgumentException: Contribution
org.domain.etss.services.AppModule.contributeSecurityConfiguration(Configuration,
SecurityFilterChainFactory) (at AppModule.java:312) is for service
'SecurityConfiguration', which does not exist. at
org.apache.tapestry5.ioc.internal.RegistryImpl.validateContributeDefs(RegistryImpl.java:236)
at
org.apache.tapestry5.ioc.internal.RegistryImpl.<init>(RegistryImpl.java:200)
at org.apache.tapestry5.ioc.RegistryBuilder.build(RegistryBuilder.java:170)
at
org.domain.etss.services.form.TimeSheetServiceTest.setup(TimeSheetServiceTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:551)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213) at
org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138) at
org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:175)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:107) at
org.testng.TestRunner.privateRun(TestRunner.java:768) at
org.testng.TestRunner.run(TestRunner.java:617) at
org.testng.SuiteRunner.runTest(SuiteRunner.java:334) at
org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329) at
org.testng.SuiteRunner.privateRun(SuiteRunner.java:291) at
org.testng.SuiteRunner.run(SuiteRunner.java:240) at
org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53) at
org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:87) at
org.testng.TestNG.runSuitesSequentially(TestNG.java:1188) at
org.testng.TestNG.runSuitesLocally(TestNG.java:1113) at
org.testng.TestNG.run(TestNG.java:1025) at
org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:72)
at
org.apache.maven.surefire.testng.TestNGXmlTestSuite.execute(TestNGXmlTestSuite.java:88)
at
org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:101)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
at com.sun.proxy.$Proxy0.invoke(Unknown Source) at
org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:150)
at
org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:91)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
]]>
</failure></testcase>
<!-- testService -->
</testsuite>

>From this line

public static void
contributeSecurityConfiguration(Configuration<SecurityFilterChain>
configuration,

SecurityFilterChainFactory factory) {

configuration.add(factory.createChain("/employee/**").add(factory.roles(),
"employee").build());
        configuration.add(factory.createChain("/").add(factory.roles(),
"user").build());
    }

What am I missing?


On Tue, Jan 21, 2014 at 1:00 PM, Dmitry Gusev <dmitry.gu...@gmail.com>wrote:

> Right, this is for integration testing. I use mocking too, but rarely -- my
> tests are 80% integration ones and involve DB (the same as in production).
> For mocks I have to use constructor injection also, and this is the only
> reason why I use constructor injections.
> The code looks ugly in this cases, though, when you have more than 5
> dependencies per service. And it's also a tedious task when you want to add
> another dependency to the service, because you have to update all test
> clients also. That's why I prefer @Inject.
>
> It would be nice to have some api to override, decorate, and advise some
> services on existing (built) registry instance right in the test method.
> Maybe (temporarily) replace some service with a mock. So that I won't have
> to build new module just to override one service for one test case, because
> it requires additional setup. Just a thoughts.
>
>
> On Tue, Jan 21, 2014 at 9:41 PM, Dragan Sahpaski
> <dragan.sahpa...@gmail.com>wrote:
>
> > I agree with Dimitry but thats more for integration like testing.
> > For basic unit testing of services methods (usually we unit test a single
> > method per test) we mock the dependencies (the injected services) and
> pass
> > the mocks through the constructor of the service implementation class
> under
> > test. That's why we prefer constructor based injection.
> >
> > If we need to mock methods in the service that's being bested than we
> > usually use Spy in Spock or the equivalent feature in other mock
> > frameworks.
> >
> > Cheers,
> > Dragan Sahpaski
> >
> >
> > On Tue, Jan 21, 2014 at 6:34 PM, Dmitry Gusev <dmitry.gu...@gmail.com
> > >wrote:
> >
> > > I usually create base class where I construct registry instance, then I
> > use
> > > registry.getService(Intf.class) when I need an instance of a service.
> > >
> > > Like here:
> > >
> > >
> >
> https://github.com/anjlab/anjlab-tapestry-commons/blob/master/anjlab-tapestry-quartz/src/test/java/com/anjlab/tapestry5/services/quartz/SchedulerTest.java
> > >
> > >
> > > On Tue, Jan 21, 2014 at 9:07 PM, George Christman
> > > <gchrist...@cardaddy.com>wrote:
> > >
> > > > Hello, we are trying to unit test our services, but our services
> > contain
> > > > other injected services. I'm wondering how you test injected
> services.
> > Is
> > > > there a configuration I'm missing?
> > > >
> > > > --
> > > > George Christman
> > > > www.CarDaddy.com
> > > > P.O. Box 735
> > > > Johnstown, New York
> > > >
> > >
> > >
> > >
> > > --
> > > Dmitry Gusev
> > >
> > > AnjLab Team
> > > http://anjlab.com
> > >
> >
>
>
>
> --
> Dmitry Gusev
>
> AnjLab Team
> http://anjlab.com
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Reply via email to