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