We are using the Jersey Test Frameworks for API testing. In test-mode, we use an h2 database, mysql in production. Everything is fine to this point.
Now i want to write tests for our repositories to check if the data is written properly to the database.
I can't inject any classes in my tests so i am using the standard constructor the create an new instance of RepositoryA. Works for me.
Now the problem: RepositoryA is now injecting an instance of RepositoryB. And injection isn't working on test-scope.
Is it possible to get injection running in this environment?
Depending on the versions of the libraries you are using, running CDI in JUnit Test is different.
First you need to add this dependency, selecting the right version :
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit5</artifactId> // or weld-junit4
<version>1.3.0.Final</version>
<scope>test</scope>
</dependency>
Then you can enable Weld in your JUnit test. Here is an example of injecting a repository for an entity class called VideoGame :
#Slf4j
#EnableWeld
class VideoGameRepositoryTest
{
#WeldSetup
private WeldInitiator weld = WeldInitiator.performDefaultDiscovery();
#Inject
private VideoGameRepository repo;
#Test
void test()
{
VideoGame videoGame = VideoGameFactory.newInstance();
videoGame.setName("XENON");
repo.save(videoGame);
// testing if the ID field had been generated by the JPA Provider.
Assert.assertNotNull(videoGame.getVersion());
Assert.assertTrue(videoGame.getVersion() > 0);
log.info("Video Game : {}", videoGame);
}
}
The important parts are :
the #EnableWeld placed on the JUnit test class.
the #WeldSetup placed on a WeldInitiator field, to lookup to all annotated classes.
don't forget beans.xml in META-INF of your test classpath in order to setup the discovery-mode.
#Slf4j is a lombok annotation, you don't need it (unless you are already using Lombok)
Here the VideoGameRepository instance benefits injection as well, like in a classical CDI project.
Here is the code of the VideoGameFactory which gets a brand new instance of the entity class marked with #Dependent scope. This factory programmatically invokes the CDI current context.
public class VideoGameFactory
{
public static VideoGame newInstance()
{
// ask CDI for the instance, injecting required dependencies.
return CDI.current().select(VideoGame.class).get();
}
}
Alternately, you can have a look to Arquillian which can come with a full Java EE server in order to have all the needed dependencies.
Related
I'm using Sitecore 8.1 MVC with Autofac as the DI. I was wondering what is the recommended way to injecting resolved objects into sitecore created objects i.e. pipelines, commands, computed fields etc... As an example, i am using a membership provider in which i need to invoke my business layer. Is it possible for me to define a constructor on the class and sitecore would injects the objects?
Thanks
With things like pipeline processors, commands etc... Basically anything that Sitecore creates - you are fairly limited. The normal approach is to use the Service Locator pattern to resolve dependencies:
var membershipProvider = DependencyResolver.Current.Resolve<IMembershipProvider>()
There are other ways tho. This post: https://cardinalcore.co.uk/2014/07/02/sitecore-pipelines-commands-using-ioc-containers/ uses a container factory class to resolve the dependencies in the pipeline. This is the class used:
using System;
using System.Diagnostics.CodeAnalysis;
using Sitecore.Reflection;
public class ContainerFactory : IFactory
{
private readonly IContainerManager containerManager;
public ContainerFactory() : this(new LocatorContainerManager()) // service locate an appropriate container
{
}
public ContainerFactory(IContainerManager containerManager)
{
this.containerManager = containerManager;
}
public object GetObject(string identifier)
{
Type type = Type.GetType(identifier);
return this.containerManager.Resolve(type);
}
}
Then this would be setup as the factory for the event or processor using the factory attribute in the config. Example config:
<sitecore>
<events>
<event name="item:saved">
<handler factory="ContainerFactory" ref="MyApp.MyHandler, MyApp" method="MyMethod">
<database>master</database>
</handler>
</event>
</events>
<pipelines>
<MyPipeline>
<processor type="1" factory="ContainerFactory" ref="MyApp.MyProcessor, MyApp" />
</MyPipeline>
</pipelines>
<factories>
<factory id="ContainerFactory" type="MyApp.ContainerFactory"></factory>
</factories>
</sitecore>
With this second method, you can inject your dependencies in your constructor as you normally would.
These are probably the 2 most commonly used options.
I'm still trying to get my head around what's what with ASP.NET 5 / EF 7. I'm using DNX projects (.xproj).
Startup is used by OWIN/ASP.NET for configuring, loading services, etc. But it's also used for EF 7 migrations (to set your DbContextOptions for example).
My main goal is to know how EF7 (and ASP.NET 5) bootstrap with Startup and who's creating the startup class, initializing the DI container, etc.
An example of what I need to do, for context, is that in my xUnit unit tests (which are in their own assembly and reference my data assembly which doesn't have a Startup class), I need to AddDbContext to set my connection.
I have the sample startup class:
namespace Radar.Data
{
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Hosting;
using Microsoft.Data.Entity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.PlatformAbstractions;
public class Startup
{
public IConfigurationRoot Configuration { get; set; }
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.SetBasePath(appEnv.ApplicationBasePath)
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<RadarDbContext>(options =>
options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));
}
public void Configure(IApplicationBuilder app)
{
}
}
}
This is currently in my data assembly and not my unit test assembly. I tried adding the app setting (I know it's OWIN but I thought I'd give it a shot):
<appSettings>
<add key="owin:appStartup" value="Radar.Data.Startup, Radar.Data" />
</appSettings>
The startup class is not getting executed.
I'd really like an understanding of the overall mechanism with Startup, who calls it, etc., but for now, I just need an understanding of how EF 7 initializes dependencies/services so that I can properly initialize my unit tests.
UPDATE
Here's what I've got in my unit test so far and I thought I had it working at one point:
ServiceCollection serviceCollection = new ServiceCollection();
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
DbContextActivator.ServiceProvider = serviceProvider;
serviceCollection.AddEntityFramework()
.AddSqlServer()
.AddDbContext<RadarDbContext>(
options => options.UseSqlServer("Server=.;Database=SonOfRadar;Trusted_Connection=True;MultipleActiveResultSets=True"));
but now I'm getting No service for type 'Microsoft.Data.Entity.Internal.IDbSetInitializer' has been registered when my DbContext is instantiated. So obviously not getting all the EF services loaded.
If I comment out:
DbContextActivator.ServiceProvider = serviceProvider;
it errors earlier with: No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services.
Setting DbContextActivator.ServiceProvider is the only place in EF7 where I can find a hook to set your own provider. I'd be just as happy getting an instance of EF7's internal service collection and working with that. I think I'm going to scour the EF7 unit test code again and see if I'm missing a critical piece.
Startup class is created by Microsoft.AspNet.Hosting package when you run you web application (see StartupLoader.cs).
You can also look onto WebApplication.Run method (WebApplication.Run) its an entry point to ASP.NET 5 web applications.
DI is initialized in WebHostBuilder class (WebHostBuilder.cs) and inside dnx in Bootstrapper class (Bootstrapper.cs)
I need to intercept calls to private methods in Grails services. The following aspect IS working for any annotated public methods, however nothing happens when the annotation is at PRIVATE methods.
import exceptions.DwcpExeption
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Component
#Aspect
#Component
public class LoggerInterceptor {
private static Logger log = LoggerFactory.getLogger(LoggerInterceptor.class);
#Around("#annotation(newAnnotation)")
public Object aroundEvents(ProceedingJoinPoint proceedingJoinPoint, NewAnnotation newAnnotation) {
log.info newAnnotation.value()
String logMessage = String.format("%s.%s(%s)",
proceedingJoinPoint.getTarget().getClass().getName(),
proceedingJoinPoint.getSignature().getName(),
Arrays.toString(proceedingJoinPoint.getArgs()));
log.info "*Entering $logMessage"
def result
try {
result = proceedingJoinPoint.proceed()
catch (ex) {
log.error '', ex
}
log.info "*Exiting $logMessage. Result: $result"
return result
}
}
Maybe the problem is in config? I've tried in applicationContext.xml
<aop:aspectj-autoproxy proxy-target-class="true"/>
and in resources.groovy
aop.config("proxy-target-class": true)
Nevertheless, only public methods are intercepted.
Spring AOP is a proxy-based "AOP lite" approach in comparison to AspectJ. It only works for Spring components and only for public, non-static methods. This is also explained in the Spring AOP documentation as follows:
Due to the proxy-based nature of Spring’s AOP framework, protected methods are by definition not intercepted, neither for JDK proxies (where this isn’t applicable) nor for CGLIB proxies (where this is technically possible but not recommendable for AOP purposes). As a consequence, any given pointcut will be matched against public methods only!
If your interception needs include protected/private methods or even constructors, consider the use of Spring-driven native AspectJ weaving instead of Spring’s proxy-based AOP framework. This constitutes a different mode of AOP usage with different characteristics, so be sure to make yourself familiar with weaving first before making a decision.
Bottom line: Please switch to AspectJ which can be easily integrated into Spring applications via LTW (load-time weaving) as described in Section 9.8, “Using AspectJ with Spring applications”.
If you don't specify the scope it defaults to public. Add a pointcut for private methods:
#Around("#annotation(newAnnotation) && execution(private * *(..))")
I have built an application with the dependency framework Guice. Now I will move over to OSGI and started to extend my jars with bundle information.
The main problem, which I currently face is, how to set up the dependency injection correctly. I have bundle A, which exports some packages. Then Bundle B defines a component, which needs some object (class AA) of bundle A injected.
I could set up a service for the class AA in bundle A, which will be injected automatically, but what if bundle A has also a dependency to some class in bundle A, which is maybe not exported. Do I have to set up the second class then also as service, which will not work, because it is not exported.
The following code will show the problem:
Bundle A
package test.bundleA.api
public class AA {
#Inject
public AA(AInternal someReference) {...}
}
package test.bundleA.internal
public class AInternal {...}
Bundle B:
package test.bundleB.api
public class ComponentB {
#Inject
public ComponentB(AA refToA) {...}
}
When I will use any other classes in bundle A from the exported package, do I have then to set up for each of them a service?
What is a common approach to solve the problem of dependency injection inside the bundle and even over bundle boundaries?
If you are independent of using Guice I would recommend to use Eclipse+Bndtools to create your OSGi bundles. With Bndtools, its quite easy to create OSGi bundles and also DI via Annotations. Let's take an example:
You have an interface in bundleA:
public interface Greeting {
String sayHello(String name);
}
An implementation in bundleB where #Component enables our bundle to use OSGi Declarative Service.
#Component
public class ExampleComponent implements Greeting {
public String sayHello(String name) {
return "Hello " + name;
}
}
And in the end a third bundleC where you want to us DI and inject all Greeting implementation to a specific component for usage.
#Component
public class GreetingCommand {
private Greeting greetingSvc;
#Reference
public void setGreeting(Greeting greetingSvc) {
this.greetingSvc = greetingSvc;
}
public void greet(String name) {
System.out.println(greetingSvc.sayHello(name));
}
}
As you can see with #Reference you indicate that you want to inject an implementation of your Greeting interface. The example above uses OSGi Declarative Services in combination with Bndtools. Bndtools itself takes the annotations and creates a XML file needed for OSGi to use Declarative Services. I don't want to go more deep into it. Please see [1] and [2] for more information. Just wanted to show you how DI is made by using declarative services and Bndtools.
[1] http://bndtools.org/
[2] http://wiki.osgi.org/wiki/Declarative_Services
Well, there is a extension library called Peaberry which provide integration Guice with OSGi. There is nice example how to inject a service bundle into another bundle.
Hope you will find it helpful.
The solution to your specific scenario is to define a public factory (builder) service/component that you can register with osgi and inject that type. The factory impl can be defined in the same module, and create the internal type via a 'create' or 'build' method with a return type of a public interface type, but the impl is internal.
Using the Spock (0.7) Grails (2.1.2) plugin you can write integration specifications that automatically inject Grails archetypes (like services). However, I would like to do the same thing for Spring beans declared only in my resources.groovy. For example:
beans = {
simpleBean(SimpleBean) {
// load some dependencies
}
}
Where SimpleBean is declared in the src/groovy folder. If this were a Grails service, I could write something like the following in my test/integration folder::
import grails.plugin.spock.IntegrationSpec
class SimpleBeanSpec extends IntegrationSpec {
def simpleBean
def "should"() {
when:
data = simpleBean.load()
then:
assert simpleBean
}
}
But the above throws a NullPointerException on the call to simpleBean.load(). Is there some way to get Spock/Grails to create the the simpleBean dependency so that it has all the configured depdencies from resources.groovy as you would a Grails service?
Grails automatically injects all beans into integration tests, including Spock tests. Beans declared in resources.conf should work the same as artefacts. Are your IntegrationSpecs located under test/integration?