Ok first thing:
You should not test abstract classes but the concrete class which extends your base class. You can use google to find various reasons for this. The most obvious one is, that a subclass may change the behavior of a super class and therefore break the contract you have tested.
Never the less here is how you can do it:
Take your second approach and change the before method to
@Before
public void setupMocks(Injector injector) throws SQLException {
when(dataSource.getConnection()).thenReturn(connection);
holder = mock(AbstractConnectionHolder.class, CALLS_REAL_METHODS);
injector.injectMembers(holder);
}
This should inject the dependencies into your mock.
Hi All,--I'm trying to test an abstract class that has some injected fields. Basically, the class is the following:public abstract class AbstractConnectionHolder {@Injectprivate Configuration configuration;@Injectprivate ConnectionContext context;protected ConnectionContext getConnectionContext() {return context;}protected Configuration getConfiguration() {return configuration;}public Connection openConnection() {return getConnectionContext().openConnection();}public void closeConnection() {getConnectionContext().closeConnection();}public Connection getConnection() {return getConnectionContext().getConnection();}}To test it, I'm trying to create a new partial mock for every test. I've managed to run the following:@RunWith(JukitoRunner.class)public class AbstractConnectionHolderTest {@InjectDataSource dataSource;@InjectConnection connection;@InjectConfiguration configuration;@InjectConnectionContext context;public static class Module extends JukitoModule {@Overrideprotected void configureTest() {bind(Configuration.class).toInstance(new Configuration(new PostGISTemplates()));bind(AbstractConnectionHolder.class).toInstance(mock(AbstractConnectionHolder.class, CALLS_REAL_METHODS));}}@Beforepublic void setupMocks() throws SQLException {when(dataSource.getConnection()).thenReturn(connection);}@Testpublic void shouldReturnConfiguration(AbstractConnectionHolder holder) {assertThat(holder.getConfiguration(), is(configuration));}}This runs, but it only allows me to have a single AbstractConnectionHolder mock for all tests. The ideal case would be to make it somehow inject a new AbstractConnectionHolder partial mock into each test, which I couldn't figure out how to do. Is this possible?I also tried to manually create mocks in the @Before method as follows:@RunWith(JukitoRunner.class)public class AbstractConnectionHolderTest {@InjectDataSource dataSource;@InjectConnection connection;@InjectConfiguration configuration;@InjectConnectionContext context;AbstractConnectionHolder holder;public static class Module extends JukitoModule {@Overrideprotected void configureTest() {bind(Configuration.class).toInstance(new Configuration(new PostGISTemplates()));}}@Beforepublic void setupMocks() throws SQLException {when(dataSource.getConnection()).thenReturn(connection);holder = mock(AbstractConnectionHolder.class, CALLS_REAL_METHODS);}@Testpublic void shouldReturnConfiguration() {assertThat(holder.getConfiguration(), is(configuration));}}However, this fails with the following exception:java.lang.AssertionError:Expected: is <com.mysema.query.sql.Configuration@7a79dbc7>but: was nullat org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)at org.junit.Assert.assertThat(Assert.java:865)at org.junit.Assert.assertThat(Assert.java:832)at test.AbstractConnectionHolderTest.shouldReturnConfiguration(AbstractConnectionHolderTest.java:66)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:606)at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)at org.jukito.InjectedStatement.evaluate(InjectedStatement.java:96)at org.jukito.InjectedBeforeStatements.evaluate(InjectedBeforeStatements.java:51)at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)at org.junit.runners.ParentRunner.run(ParentRunner.java:309)at org.jukito.JukitoRunner.run(JukitoRunner.java:187)at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)As I understand, for some reason in this case it wasn't able to inject the fields of AbstractConnectionHolder. Is there a way to solve the original problem or this injection issue?Thanks a lot!Best regards,Anton
You received this message because you are subscribed to the Google Groups "Jukito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jukito+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
I had the same idea when I started with TDD and stumbled over an abstract class.
I didn't use mockito but wrote my own concrete subclass which implemented all abstract methods by doing nothing...
In the end I had a bunch of duplicated tests. Since I tested the behavior of the abstract class through my special subclass and the productive subclasses. Some of the productive sub classes altered the behavior of the base class slightly. So I could not declare the method in the abstract class as final.
In the end I changed my abstract class to be an interface and moved all implementation which previously was in the abstract class to a new helper class. In the subclasses of my new interface I delegated the calls to the new helper class.
Using delegation I could test the common behavior in the helper class. And I could test which implementation of the interface relay on the default behavior and which defined there own logic.