Spring's ContextConfiguration can do this for you.
For example, in the test context below the "Local" classes are mocks. NotificationService
is the class I want to test.
I am using component scanning to bring the mocks into the context but you can just as easily use <bean>
declarations. Note the use of use-default-filters="false".
<context:component-scan base-package="com.foo.config" use-default-filters="false">
<context:include-filter type="assignable"
expression="com.foo.LocalNotificationConfig"/>
</context:component-scan>
<context:component-scan base-package="com.foo.services.notification"
use-default-filters="false">
<context:include-filter type="assignable"
expression="com.foo.services.notification.DelegatingTemplateService"/>
<context:include-filter type="assignable"
expression="com.foo.services.notification.NotificationService"/>
</context:component-scan>
<context:component-scan base-package="com.foo.domain"/>
DelegatingTemplateService is a Groovy class with a @Delegate.
class DelegatingTemplateService {
@Delegate
TemplateService delegate
}
In the test class I use the test context and inject the service to test. In the setup I set the delegate of the DelegatingTemplateService:
@RunWith(classOf[SpringJUnit4ClassRunner])
@ContextConfiguration(Array("/spring-test-context.xml"))
class TestNotificationService extends JUnitSuite {
@Autowired var notificationService: NotificationService = _
@Autowired var templateService: DelegatingTemplateService = _
@Before
def setUp {
templateService.delegate = /* Your dynamic mock here */
}
In the service the @Autowired fields are private:
@Component("notificationService")
class NotificationServiceImpl extends NotificationService {
@Autowired private var domainManager: DomainManager = _
@Autowired private var templateService: TemplateService = _
@Autowired private var notificationConfig: NotificationConfig = _