hooking into #EJB or #PersistenceContext injection in JAX-RS unit tests - unit-testing

I'm enjoying learning JAX-RS and Jersey, but I've hit a roadblock trying to test a simple resource that needs a DAO injected, something like this:
#Stateless
#Path("simple")
public class SimpleResource {
#PersistenceContext
private EntityManager em;
// #GET, etc...
}
(I'll be moving to a more abstracted DAO pattern, but the problem is the same, i.e., how do I inject the #EJB DAO?)
In my unit tests I'm using a embedded Jetty server that configures Jersey in its web.xml, and I'd like to hook into the resource's lifecycle so that I can inject a mock EntityManager, but I've not found a clean answer after a lot of searching. Can you help? Some possible directions I've come across:
1) Use JNDI context lookup in my code to get the DAO bean, and register the mock object in the tests.
Instead of #EJB or #PersistenceContext, use something like this in the resource's constructor:
theDAO = (DAOImpl) new InitialContext().lookup("java:global/EJB/DAOImpl");
However, that means my test environment needs to support JNDI, and doing so in Jetty will probably involve some pain. Plus, it doesn't use the clean annotation approach.
2) Use method injection.
Inject into the method so that I can set the DAO post-instantiation, e.g.,
#PersistenceContext(name = "persistence/pu00")
public void setPersistenceUnit00(final EntityManager em) {
em00 = em;
}
OR
private MyEjbInterface myEjb;
#EJB(mappedName="ejb/MyEjb")
public void setMyEjb(MyEjb myEjb) {
this.myEjb = myEjb;
}
However, to do this I need the Jersey-instantiated instance, e.g., SimpleResource. How do I get that?
3) Use reflection.
A kind of DIY injection, something like:
public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) {
Field setId = instanceFieldClass.getDeclaredField(fieldName);
setId.setAccessible(true);
setId.set(instance, fieldValue);
}
Again, I need the Jersey-instantiated instance.
4) Use an Injection Provider.
I'm still sketchy on how this works, but it looks like Jersey provides a means of defining customized injectable annotations, e.g.,
#Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
if (!(t instanceof Class)) {
return null;
}
try {
Class c = (Class) t;
Context ic = new InitialContext();
final Object o = ic.lookup(c.getName());
return new Injectable<Object>() {
public Object getValue() {
return o;
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
A variation using a helper class:
Server server = new Server(8080);
Context root = new Context(server,"/",Context.SESSIONS);
ResourceConfig rc = new PackagesResourceConfig("edu.mit.senseable.livesingapore.platform.restws.representations");
rc.getSingletons().add(new SingletonTypeInjectableProvider<javax.ws.rs.core.Context, Myobj>(Myobj.class, new Myobj(12,13)){});
root.addServlet(new ServletHolder(new ServletContainer(rc)), "/");
server.start();
With this use:
#Path("/helloworld")
public class HelloWorldResource {
#Context Myobj myClass;
....
}
Is this viable for #EJB or #PersistenceContext?
5) Extend javax.ws.rs.core.Application.
Sketchy on this, but:
#javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public InjectionApplication() {
// no instance is created, just class is listed
classes.add(BookResource.class);
}
#Override
public Set<Class<?>> getClasses() {
return classes;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
6) Extend ServletContainer.
An older style of using InjectableProvider? Looks more complex:
public class ServletAdapter extends ServletContainer {
#Override
protected void configure(ServletConfig servletConfig, ResourceConfig rc, WebApplication wa) {
super.configure(servletConfig, rc, wa);
rc.getSingletons().add(new InjectableProvider<Resource, Type>() {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable<Object> getInjectable(ComponentContext ic, Resource r, Type c) {
final Holder value = new Holder();
Context ctx = new InitialContext();
try {
value.value = ctx.lookup(r.name());
} catch (NamingException ex) {
value.value = ctx.lookup("java:comp/env/" + r.name());
}
return new Injectable<Object>() {
public Object getValue() {
return value.value;
}
};
}
});
}
}
7) Use an embedded EJB container.
E.g., http://openejb.apache.org. This is pretty heavy, and I expect it's going to be messy to get working. (In fact, what started me down the "Jetty + Jersey" route was a bug in GlassFish Embedded around security logins. I also looked at other Java EE 6 application containers like JBoss AS, but each had problems in embedded mode, with limited user community support.)
8) Use a third-party IoC library like Spring or Guice.
Spring is apparently commonly used for solving these kinds of problems (injecting mocks when unit testing), but I wanted to avoid having to learn another big set of APIs - pure Java EE has been enough of a challenge! But I'm game if it's the best solution. I haven't yet looked carefully into Spring or Guice.
Have you used any of these successfully? Any other solutions you like? I'm really looking forward to your advice on this. Thanks in advance -- matt

Since you are using Netbeans, give this a try:
Using the Embedded EJB Container to Test Enterprise Applications
The tutorial uses an embedded Glassfish container and injects an EJB that encapsulates the EntityManager (similar to what you described in your first option).

If you only need an EntityManager inside your embedded Jetty container, why use injection in the first place? You can just put one of the JPA implementations (such as eclipselink or hibernate) on your class-path, configure a resource local persistence unit, then obtain it like this:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your unit name");
EntityManager em = emf.createEntityManager();
It would be enough to have something (maybe a static DAO factory?) that behaves like your #EJB for the purpose of testing your JAX-RS classes.
If you do want your unit tests to be as close to the Java EE environment as possible, look into running them with Arquillian (http://www.jboss.org/arquillian.html). It runs the tests directly on a Java EE container - it's easy, it has great documentation.

Related

How to unit test a service call in xUnit and nSubstitute

I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.

Unit testing a started Service which has a few fields injected into it?

I am a Dagger newbie.
TL;DR:
If an Android Service has any fields injected into it using Dagger, then in order to actually perform the injection, I need to have an instance of that Service.
In Robolectric tests, this corresponds to MyService service = Robolectric.buildService(MyService.class).get(). And then, objectGraph.inject(service);
However, rest of the code that actually starts MyService still uses context.startService(context, MyService.class);.
Question: What is the idiomatic way in Dagger to address this mismatch?
Let's say I have a Service as follows:
public class MyService {
#Inject Parser parser;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String data = intent.getStringExtra("data_to_be_parsed");
parser.parse(data);
}
}
Elsewhere in my code, I have an ApiClient class that does this:
public class ApiClient{
public static void parseInBackground(Context context, String data){
//This service does not have its fields injected
context.startService(new Intent(context, MyService.class).putExtra("data_to_be_parsed", data));
}
}
That parseInBackground method will be called from an Activity in response to user interaction.
Now, I'm following TDD and hence, I haven't yet written the Application Module for this. Here's the test module:
#Module(injects = MyService.class)
public class TestModule {
#Provides #Singleton Parser provideParser(){
return new MockParser();
}
}
And finally, the test case:
#RunWith(Robolectric.class)
public class ApiTest {
#Test
public void parseInBackground_ParsesCorrectly(){
//This service has its fields injected
MyService service = Robolectric.buildService(MyService.class).get();
ObjectGraph.create(new TestModule()).inject(service);
ApiClient.parseInBackground(Robolectric.application, "<user><name>droid</name></user>");
//Asserts here
}
}
As you can see, in the test, I retrieve an instance of the service and then inject the MockParser into it. However, the ApiClient class directly starts the service using an Intent. I don't have a chance to perform the injection.
I am aware that I can have MyService perform an injection on itself:
public void onCreate(){
ObjectGraph.create(new TestModule()).inject(this);
}
But then, I am hardcoding the TestModule here.
Is there an existing idiom in Dagger to set up dependencies for such situations?
It's the wrong way to hardcode your modules either in tests or in services. Better approach is to perform creation via your custom Application object which in turn will hold singleton ObjectGraph object. For example:
// in MyService class
#Override public void onCreate() {
super.onCreate();
MyApp.from(context).inject(this);
}
// in MyApp class
public static MyApp from(Context context) {
return (MyApp) context.getApplicationContext();
}
//...
private ObjectGraph objectGraph;
#Override public void onCreate() {
// Perform Injection
objectGraph = ObjectGraph.create(getModules());
objectGraph.inject(this);
}
public void inject(Object object) {
objectGraph.inject(object);
}
protected Object[] getModules() {
// return concrete modules based on build type or any other conditions.
}
Alternatively, you can refactor last method out into separate class and make different implementations for different flavors or build types. Also you may want to set overrides=true in your TestModule's annotation.

Moq'n Complex Methods

I have inherited a mess of a code base and I have been asked to attempt to right effective "unit tests" and automated tests to support upcoming changes. We are using Crm 4.0. Here is an example of the code I am trying to Moq:
public static creditdebitcardEntity CreateCreditCardInstance(Transaction transaction, TransactionSet transactionSet, accountEntity stetyAccount)
{
try
{
//todo: check for existance
creditdebitcardEntity stetyCard;
ColumnSet customColumns = new ColumnSet();
customColumns.Attributes = new string[]{creditdebitcardEntity.creditdebitcardidName,
creditdebitcardEntity.expirationmonthName,
creditdebitcardEntity.expirationyearName,
creditdebitcardEntity.reasonheldName,
creditdebitcardEntity.heldonName,
creditdebitcardEntity.statuscodeName};
creditdebitcardEntity[] tempCard =
creditdebitcardDal.GetCreditCardEntityByHashcode(transaction.CreditCards.CreditCardHash, customColumns);
if (tempCard != null)
return tempcard;
else
return null;
}
catch (Exception ex)
{
DirectiveExceptions.ReturnStagingException("CreditCardDirectives", "CreateCreditCardInstance", "An error occurred when trying to create a credit card transaction instance for folio " + transaction.SourceTransactionID + ". Contact a system administrator", ex, transaction.SourceTransactionKey);
return null;
}
}
so my question is this; how do I mock out the call to the CreditDebitCardDal? I cannot make changes to the code base without having to go through a bunch of wickets. I can introduce new code with little effort, but modifying the existing code requires a lot of regression testing.
I do understand how to mock out the call to the static method and passing in the required objects is no issue at all either. I just don't want to rely on my SUT having a Crm database to ensure that the code is working. I am thinking that I could create an Interface to the Dal Class and then mock that interface, but wanted to see if there was a better way before I started down that road.
Thanks and let me know if I can provide any additional details.
Chuck
I would mock out the parameters to start with. Extract an interface from Transaction, TransactionSet, accountEntity. From this you can then mock out the dependencies. You will have some more work to do but should be along the lines of below. The code below is just to show you, it is not tested or compiled
[TestFixture]
public class CreditDebitCardUnitTests
{
private Mock<ITranscation> MockTransaction {get ; set;}
private Mock<ITransactionSet> MockTransactionSet {get; set;}
private Mock<IAccountEntity> MockAccountEntity {get; set;}
[Setup]
public void TestFixtureSetup()
{
MockTransaction = new Mock<ITransaction>();
MockTransactionSet = new Mock<ITransactionSet>();
MockAccountEntity = new Mock<IAccountEntity>();
}
[Test]
[Category("CreditCard tets")]
public void VerfiyCreditDebitCardDal_GetCreditCardEntityByHashcode_Gets_Called
{
//Arrange
ColumnSet customColumns = new ColumnSet();
customColumns.Attributes = new string[]{creditdebitcardEntity.creditdebitcardidName,
creditdebitcardEntity.expirationmonthName,
creditdebitcardEntity.expirationyearName,
creditdebitcardEntity.reasonheldName,
creditdebitcardEntity.heldonName,
creditdebitcardEntity.statuscodeName};
MockTransaction.Setup(x => x.CreditCards.CreditCardHash).Returns(It.IsAny<Hash>)
//Act
creditdebitcardEntity[] tempCard =
creditdebitcardDal.GetCreditCardEntityByHashcode(MockTransaction.ObjectCreditCards.CreditCardHash, customColumns )
//Assert
}
}

Robolectric: simulate network error in test

How is it possible to produce the same exception like during a real connection-error in robolectric tests?
I want to how the program acts if the network is currently not available. Is there a possibility to produce the same exception for my HttpClient?
I already tried:
Robolectric.getFakeHttpLayer().interceptHttpRequests(false); // with real network to a non existent IP
and
WifiManager wifiManager = (WifiManager) activity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
and
Robolectric.addPendingHttpResponse(404, null);
but none of them produces the same reactions like a real connection-loosing.
Thank you
I've checked Robolectric's FakeHttpLayer and haven't found way to simulate throwing an IOException.
So use mocking to make it working for you. First introduce HttpClientFactory (if you use HttpClient, you can use same approach for HttpUrlConnection):
public class HttpClientFactory {
public HttpClient createClient() {
return new DefaultHttpClient();
}
}
And now in your networking layer use factory instead of constructors (let for simplicity assume that it is synchronous):
public class HttpTransportLayer {
private final HttpClientFactory clientFactory;
public HttpTransportLayer() {
this(new HttpClientFactory());
}
// For tests only
HttpTransportLayer(HttpClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
public String requestData(String url) {
HttpClient client = factory.createClient();
...
}
}
So now you can in tests use Mockito:
HttpClient mockedClient = mock(HttpClient.class);
#Before
public void setUp() {
HttpClientFactory factory = mock(HttpClientFactory.class);
when(factory.createClient()).thenReturn(mockedClient);
target = new HttpTransportLayer(factory);
}
#Test
public void whenIOExceptionThenReturnNull() {
when(mockedClient.execute(any(HtptUriRequest.class))).thenThrow(new IOException());
String data = target.requestData("http://google.com");
assertThat(data).isNull();
}
That is dummy test and usually nobody will return null in case of error.
You could also task look to some dependency injection framework like Dagger to minimise injection code.
If you use any good framework for networking like Retrofit or Volley then it is even simpler - you don't need to mock anything and just invoke you error callback.
Hope it helps

How to use JUnit with EJB3 and JPA

I'm trying to test my Session Beans with JUnit, but I can't. I've tried a lot of method, but still get some exceptions.
Here is what I need:
I have a few Stateless Session Beans I need to test. Each has the same #PersistenceContext and uses an EntityManager
With my test cases I need to test their methods. For instance: if I add an user with username X and then I try to add another one with the same username, I want to catch an Exception.
Can someone provide a simple and short generic test example? I've already read many, but I always get an error (I get NullPointerException for the EntityManager when I call a method like: sessionBean.method() (which does, for instance, entityManager.find(...)), or I am not able to initialize the Context, or other PersistenceException).
You might be interested in one of the latest posts of Antonio Goncalves:
WYTIWYR : What You Test Is What You Run
It tells about testing EJB with EntityManager using:
Mockito,
Embedded EJB Container,
Arquillian.
I solved creating a Stateless Session Bean and injecting its Entity Manager to test classes. I post the code in case someone will need it:
#Stateless(name = "TestProxy")
#Remote({TestProxyRemote.class})
public class TestProxy implements TestProxyRemote {
#PersistenceContext(unitName = "mph")
private EntityManager em;
#Override
public void persist(Object o) {
em.persist(o);
}
#Override
public void clear() {
em.clear();
}
#Override
public void merge(Object o) {
em.merge(o);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, String key) {
return em.find(classe, key);
}
#Override
#SuppressWarnings({ "rawtypes", "unchecked" })
public Object find(Class classe, long key) {
return em.find(classe, key);
}
#SuppressWarnings("rawtypes")
#Override
public List getEntityList(String query) {
Query q = em.createQuery(query);
return q.getResultList();
}
}
public class MyTest {
#BeforeClass
public static void setUpBeforeClass() throws NamingException {
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
env.setProperty(Context.PROVIDER_URL, "localhost:1099");
env.setProperty("java.naming.factory.url.pkgs","org.jboss.naming:org.jnp.interfaces");
jndiContext = new InitialContext(env);
try {
proxy = (TestProxyRemote) jndiContext.lookup("TestProxy/remote");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
Then I can use proxy.find() to get the entities I need, o proxy.getEntityList() to execute a query to retrieve all the instance of an Entity. Or I can add other methods if I want.
Unitils provides a really cool support for JPA. Unitils can be used with JUnit or TestNG and in case you need a mocking framework, Unitils provides its own mocking module as well as support for EasyMock.
#JpaEntityManagerFactory(persistenceUnit = "testPersistenceUnit")
#DataSet(loadStrategy = RefreshLoadStrategy.class)
public class TimeTrackerTest extends UnitilsTestNG {
#TestedObject
private TimeTrackerBean cut = new TimeTrackerBean();
#InjectInto(target="cut",property="em")
#PersistenceContext
private EntityManager em;
#Test
#DataSet("TimeTrackerTest.testAddTimeSlot.xml")
public void yourTest() {
...
}
}
#JpaEntityManagerFactory - Used to specify your persistence unit. It automatically picks up the persistence.xml from your project classpath.
#DataSet - Just in case you need to load any test data you can use this.
#TestedObject - Marks your Class Under Test
#PersistenceContext - Automatically creates your EntityManager instance from the configurations made in the persistence.xml - PersistenceUnit.
#InjectInto - Injects the em instance into the target (cut)
For more information refer this.
Hope this helps.
I'm using Needle for this. It works well with Mockito and EasyMock if you want to mock other objects.
First I write a persistencte.xml for tests (src/test/resources/META-INF) like this:
<persistence-unit name="rapPersistenceTest" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:~/test"/>
...
</properties>
</persistence-unit>
In my Junit-Testclass I write:
public class DaoNeedleTest {
//here Needle will create persistenceContext for your testclass
public static DatabaseRule databaseRule = new DatabaseRule("rapPersistenceTest");
//here you can get the entityManager to manipulate data directly
private final EntityManager entityManager = databaseRule.getEntityManager();
#Rule
public NeedleRule needleRule = new NeedleRule(databaseRule);
//here you can instantiate your daoService
#ObjectUnderTest
DAOService daoService;
#Test
public void test() {
//if your method needs a transaction here you can get it
entityManager.getTransaction().begin();
daoService.yourMethod();
entityManager.getTransaction().commit();
}
You also need a Needle-configuration File in src/test/resources, where you tell what kind of Mock-provider you are using. E.g. I'm using Mockito:
mock.provider=de.akquinet.jbosscc.needle.mock.MockitoProvider
That's it.