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
}
}
Related
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.
Well, I'm looking for the best way to refactor a (huge) legacy code-base and introducing some tests in it..There was no test framework. (yeah, I mean not at all)
It was an JEE 5 application. The goal is to revamp that in JEE7
Let me introduce a quick overview .
The end-users (those of them who are authorized) are free to evolve , configure many aspect of the application behavior by setting in the UI a bunch of preferences.
Theses are stored in an SQL table for the main part (the rest in some xml and properties files).
To fulfill this requirement, there is an #Startup object dedicated to build a sort-of huge map with all key-values.
Then all across the code base when a use case needs to adapt it's processing it checks the current value of the parameter(s) needed to its task.
A real case is that the app has to do a few operations on images;
For instance, Class ImgProcessing has to create thumbnail of a picture via this method :
Optional<Path> generateThumb_fromPath(Path origImg);
for this the method generateThumb_fromPath, calls Thumbnailer,
which uses a generic ImageProcessingHelper,
which holds a few set of generic image related tools and methods,
and specially an static method returning the wished dimensions of the thumbnail to be generated based on the original image constraints and some thumbnail preferences (keys = "THUMBNAIL_WIDTH" and "THUMBNAIL_HEIGHT").
These preferences are the user wishes for what size a thumbnail should have.
So far so good, nothing special.
Now the dark side of this :
The original JEE5 config loader is an bad old fashioned infamous singleton pattern as :
OldBadConfig {
private static OldBadConfig instance ;
public static getInstance(){
if(instance==null){
// create, initialize and populate our big preferences' map
}
return instance;
}
}
Then all across the whole code-base these preferences are used. In my refactoring effort I've already done using #Inject for injecting the singleton object.
But in static utilities ( no injection point available ) you have lots of this nasty calls :
OldBadConfig.getInstance.getPreference(key, defaultValue)
(Briefly I will explain that I use testNg + Mockito, I don't think the tools are relevant here, it seems to be more about an original terrible design,
but if I HAVE to change my toolbox (Junit or whatever) I will. But again I don't think the tooling is the root problem here. )
Trying to refactor the image part and make it test-friendly., I want to do this test with cut = instance of my Class Under Test:
#Test
public void firstTest(){
Optional<Path> op = cut.generateThumb_fromPath(targetPath);
// ..assertThatTheThumbnailWasCreated........
}
So in a few words ,
the execution flow will be like :
class under test --> some business implementation --> someutilities --> static_global_app_preference ---> other_class-othermethod.finalizingProcessing,
then return to the caller.
My testing effort halts here. How to mock the static_global_app_preference ?
How can I refactor the static_global_app_preference part from
*OldBadConfig.getInstance.getPreference(key, defaultValue)*
to something mockable where I could mock like :
Mockito.when(gloablConf.getPreference("THUMBNAIL_WIDTH", anyString)).thenReturn("32");
I've spent quite a time reading boks, blog posts etc all saying
'(these kind of) Singleton is EVIL'. You should NOT do that !
I think we all agree , thanks.
But what about a real word and effective solution to such really trivial, common tasks?
I can not add the singleton instance (or the preferences'map ) as parameters (because as it is already spread all across the code-base it will pollute all and every classes and methods . For instance in the exposed use case, it will pollute 5 methods in 4 classes just for one, poor, miserable, access to a parameter.
It's really not feasible.
So far I tried to refactor OldBadConfig class in two part : one with all initialization/write stuff,
and the other with only the read parts. that way I can at least make this a real JEE #Singleton and benefits from concurrent access once the startup is over and the configuration all loaded.
Then I tried to make this SharedGlobalConf accessible via a factory, called like :
SharedGlobalConf gloablConf= (new SharedGlobalConfFactory()).getShared();
then gloablConf.getPreference(key, defaultValue); is accessible.
It seems to be a little better than the original bottleneck, but didn't help at all for the testing part.
I thought the factory will ease everything but nothing like that comes out.
So there is my question :
For myself, I can split the OldBadConfig to an startup artefact doing the init and refesh, and to an SharedGlobalConf which is a JEE7 pure Singleton,
#Singleton
#ConcurrencyManagement(ConcurrencyManagementType.BEAN)
#Lock(LockType.READ)
Then, as for the legacy use case described here, How Can I make this reasonably mock-able ? Real word solutions are all welcomed.
Thanks sharing your wisdom and skills !
I will like to share my own answer.
Let's say we got these classes after the initial large OldBadConfig class was splitted :
#Startup AppConfigPopulator in charge of loading all information and populating the kind-of internal cache,
which is now a distinct SharedGlobalConf object. The populator is the only one in charge of feeding the SharedGlobalConf via :
#Override
public SharedGlobalConf sharedGlobalConf() {
if (sharedGlobalConf.isDirty()) {
this.refreshSharedGlobalConf();
}
return sharedGlobalConf;
}
private void refreshSharedGlobalConf() {
sharedGlobalConf.setParams(params);
sharedGlobalConf.setvAppTempPath_temp(getAppTempPath_temp());
}
In all components (by that I mean all Classes holding valid injection points) you just do your classic
#Inject private SharedGlobalConf globalConf;
For static utilities that can not do #Inject, we got an SharedGlobalConfFactory which handles the shared data to everything in a one-liner :
SharedGlobalConf gloablConf = (new SharedGlobalConfFactory()).getShared();
That way our old code base can be smoothly upgraded : #Inject in all valid components, And the (too many) old utilities that we can not reasonably rewrite them all in this refactoring step can get these
*OldBadConfig.getInstance.getPreference(key, defaultValue)*
,simply replaced by
(new SharedGlobalConfFactory()).getShared().getPreference(key, defaultValue);
And we are test-compliant and mockable !
Proof of concept :
A really critical Business demands is modeled in this class :
#Named
public class Usage {
static final Logger logger = LoggerFactory.getLogger(Usage.class);
#Inject
private SharedGlobalConf globalConf;#Inject
private BusinessCase bc;public String doSomething(String argument) {
logger.debug(" >>doSomething on {}", argument);
// do something using bc
Object importantBusinessDecision = bc.checks(argument);
logger.debug(" >>importantBusinessDecision :: {}", importantBusinessDecision);
if (globalConf.isParamFlagActive("StackOverflow_Required", "1")) {
logger.debug(" >>StackOverflow_Required :: TRUE");
// Do it !
return "Done_SO";
} else {
logger.debug(" >>StackOverflow_Required :: FALSE -> another");
// Do it another way
String resultStatus = importantBusinessDecision +"-"+ StaticHelper.anotherWay(importantBusinessDecision);
logger.debug(" >> resultStatus " + resultStatus);
return "Done_another_way " + resultStatus;
}
}
public void err() {
xx();
}
private void xx() {
throw new UnsupportedOperationException(" WTF !!!");
}
}
To get it's job done , we need a hand from our old companion StaticHelper :
class StaticHelper {
public static String anotherWay(Object importantBusinessDecision) {// System.out.println("zz #anotherWay on "+importantBusinessDecision);
SharedGlobalConf gloablConf = (new SharedGlobalConfFactory()).getShared();
String avar = gloablConf.getParamValue("deeperParam", "deeperValue");
//compute the importantBusinessDecision based on avar
return avar;
}
}
Usage of this =
#Named public class Usage {
static final Logger logger = LoggerFactory.getLogger(Usage.class);
#Inject
private SharedGlobalConf globalConf;
#Inject
private BusinessCase bc;
public String doSomething(String argument) {
logger.debug(" >>doSomething on {}", argument);
// do something using bc
Object importantBusinessDecision = bc.checks(argument);
logger.debug(" >>importantBusinessDecision :: {}", importantBusinessDecision);
if (globalConf.isParamFlagActive("StackOverflow_Required", "1")) {
logger.debug(" >>StackOverflow_Required :: TRUE");
// Do it !
return "Done_SO";
} else {
logger.debug(" >>StackOverflow_Required :: FALSE -> another");
// Do it another way
String resultStatus = importantBusinessDecision +"-"+ StaticHelper.anotherWay(importantBusinessDecision);
logger.debug(" >> resultStatus " + resultStatus);
return "Done_another_way " + resultStatus;
}
}
public void err() {
xx();
}
private void xx() {
throw new UnsupportedOperationException(" WTF !!!");
}}
As you see the old shared key/value holder is still used every where but this time, we can test
public class TestingAgainstOldBadStaticSingleton {
private final Boolean boolFlagParam;
private final String deepParam;
private final String decisionParam;
private final String argument;
private final String expected;
#Factory(dataProvider = "tdpOne")
public TestingAgainstOldBadStaticSingleton(String argument, Boolean boolFlagParam, String deepParam, String decisionParam, String expected) {
this.argument = argument;
this.boolFlagParam = boolFlagParam;
this.deepParam = deepParam;
this.decisionParam = decisionParam;
this.expected = expected;
}
#Mock
SharedGlobalConf gloablConf = (new SharedGlobalConfFactory()).getShared();
#Mock
BusinessCase bc = (new BusinessCase());
#InjectMocks
Usage cut = new Usage();
#Test
public void testDoSomething() {
String result = cut.doSomething(argument);
assertEquals(result, this.expected);
}
#BeforeMethod
public void setUpMethod() throws Exception {
MockitoAnnotations.initMocks(this);
Mockito.when(gloablConf.isParamFlagActive("StackOverflow_Required", "1")).thenReturn(this.boolFlagParam);
Mockito.when(gloablConf.getParamValue("deeperParam", "deeperValue")).thenReturn(this.deepParam);
SharedGlobalConfFactory.setGloablConf(gloablConf);
Mockito.when(bc.checks(ArgumentMatchers.anyString())).thenReturn(this.decisionParam);
}
#DataProvider(name = "tdpOne")
public static Object[][] testDatasProvider() {
return new Object[][]{
{"**AF-argument1**", false, "AF", "DEC1", "Done_another_way DEC1-AF"},
{"**AT-argument2**", true, "AT", "DEC2", "Done_SO"},
{"**BF-Argument3**", false, "BF", "DEC3", "Done_another_way DEC3-BF"},
{"**BT-Argument4**", true, "BT", "DEC4", "Done_SO"}};
}
The test is with TestNG and Mockito : it shows how we don't need to do the complex stuff (reading the sql table, the xml files etc..) but simply mock different set of values targeting just our sole business case. (if a nice fellow would accept to translate in other frameworks for those interested...)
As for the initial request was about the design allowing to reasonably refactor a -huge- existing code-base away from the 'static singleton anti-pattern' , while introducing tests and mocks I assume this a quite valid answer.
Will like to hear about your opinion and BETTER alternatives
I need a jump start in testing the methods on my Business layer. Consider the Materials BLL object, how can I test the AddNewMaterial method for it?
interface IGenericRepository<TEntity>
{
TEntity Add(TEntity m);
}
public interface IMaterialRepository : IGenericRepository<Material>
{
}
public interface IUnitOfWork
{
IMaterialRepository Materials { get; private set;}
void Save();
}
public interface IUnitOfWorkFactory
{
IUnitOfWork GetUnitOfWOrk();
}
public class MaterialsBLL
{
private readonly IUnitOfWorkFactory _uowFactory;
//uowFactory comes from DI
public MaterialsBLL(IUnitOfWorkFactory uowFactory)
{
_uowFactory = uowFactory;
}
//TODO: test this
public Material AddNewMaterial(Material m)
{
using(var uow = _uowFactory.GetUnitOfWOrk())
{
var result = uow.Materials.Add(m);
uow.Save();
return result;
}
}
I am using Moq, and XUnit, but am very green. In general I want to do this:
Mock the repositories Add method.
Mock the UoW Materials property to return my repository mock.
Mock the UoWFactory to return the UoW mock.
Create the MaterialsBLL giving the mocked UoWFactory to the contstructor.
Verify that the AddNewMaterials calls the repository's Add, and the UoW's Save, etc.
It seems to me that, I maybe should be creating a Fake MaterialRepository, rather than mocking it? Any other advice? Here is a first crack:
[Fact]
public void TestGetMaterialById()
{
var materialList = GetMaterials();
var materialRepositoryMock = new Mock<IMaterialRepository>();
materialRepositoryMock.Setup(repo => repo.Get(4)).Returns(materialList.First());
var uowMock = new Mock<IUnitOfWork>();
uowMock.SetupProperty<IMaterialRepository>(uow => uow.Materials, materialRepositoryMock.Object);
var uowFactoryMock = new Mock<IUnitOfWorkFactory>();
uowFactoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
var materialsBll = new Materials(uowFactoryMock.Object);
var result = materialsBll.Get(4);
Assert.Equal(result.MaterialId, 4);
Assert.Equal(result.Name, "Four");
}
When you feel like you need several levels of nested mock objects, there's generally something wrong with your design.
The Law of Demeter warns us here that you should probably not tinker with uow.Materials in MaterialsBLL.
Besides, a Unit of Work is typically not the place to expose Repositories. The code that needs to access Materials will usually have a direct reference to an IMaterialsRepository, not ask it from the UoW, and then the Repository implementation might reference the UoW internally.
This leads to a flatter design and simplifies your production code as well as your tests.
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
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.