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
Related
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
}
}
I have a class ClassToTest which has a dependency on ClassToMock.
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
protected void someMethod() {
...
}
}
The unit test case for ClassToTest.
public class ClassToTestTest {
private ClassToMock _mock;
#Before
public void setUp() throws Exception {
_mock = mock(ClassToMock.class)
}
}
When mock is called in the setUp() method, FileReader.readMemeber1(); is executed. Is there a way to avoid this? I think one way is to initialize the MEMBER_1 inside a method. Any other alternatives?
Thanks!
Your ClassToMock tightly coupled with FileReader, that's why you are not able to test/mock it. Instead of using tool to hack the byte code so you can mock it. I would suggest you do some simple refactorings to break the dependency.
Step 1. Encapsulate Global References
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code.
The title pretty much self explained. Instead of directly reference a global variable, you encapsulate it inside a method.
In your case, ClassToMock can be refactored into this :
public class ClassToMock {
private static final String MEMBER_1 = FileReader.readMemeber1();
public String getMemberOne() {
return MEMBER_1;
}
}
then you can easily using Mockito to mock getMemberOne().
UPDATED Old Step 1 cannot guarantee Mockito mock safely, if FileReader.readMemeber1() throw exception, then the test will failled miserably. So I suggest add another step to work around it.
Step 1.5. add Setter and Lazy Getter
Since the problem is FileReader.readMember1() will be invoked as soon as ClassToMock is loaded. We have to delay it. So we make the getter call FileReader.readMember1() lazily, and open a setter.
public class ClassToMock {
private static String MEMBER_1 = null;
protected String getMemberOne() {
if (MEMBER_1 == null) {
MEMBER_1 = FileReader.readMemeber1();
}
return MEMBER_1;
}
public void setMemberOne(String memberOne) {
MEMBER_1 = memberOne;
}
}
Now, you should able to make a fake ClassToMock even without Mockito. However, this should not be the final state of your code, once you have your test ready, you should continue to Step 2.
Step 2. Dependence Injection
Once you have your test ready, you should refactor it further more. Now Instead of reading the MEMBER_1 by itself. This class should receive the MEMBER_1 from outside world instead. You can either use a setter or constructor to receive it. Below is the code that use setter.
public class ClassToMock {
private String memberOne;
public void setMemberOne(String memberOne) {
this.memberOne = memberOne;
}
public String getMemberOne() {
return memberOne;
}
}
These two step refactorings are really easy to do, and you can do it even without test at hand. If the code is not that complex, you can just do step 2. Then you can easily test ClassToTest
UPDATE 12/8 : answer the comment
See my another answer in this questions.
UPDATE 12/8 : answer the comment
Question : What if FileReader is something very basic like Logging that needs to
be there in every class. Would you suggest I follow the same approach
there?
It depends.
There are something you might want to think about before you do a massive refactor like that.
If I move FileReader outside, do I have a suitable class which can read from file and provide the result to every single class that needs them ?
Beside making classes easier to test, do I gain any other benefit ?
Do I have time ?
If any of the answers is "NO", then you should better not to.
However, we can still break the dependency between all the classes and FileReader with minimal changes.
From your question and comment, I assume your system using FileReader as a global reference for reading stuff from a properties file, then provide it to rest of the system.
This technique is also introduced in Michael Feathers's wonderful book : Working Effectively with Legacy Code, again.
Step 1. Delegate FileReader static methods to instance.
Change
public class FileReader {
public static FileReader getMemberOne() {
// codes that read file.
}
}
To
public class FileReader {
private static FileReader singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
public String getMemberOne() {
// codes that read file.
}
}
By doing this, static methods in FileReader now have no knowledge about how to getMemberOne()
Step 2. Extract Interface from FileReader
public interface AppProperties {
String getMemberOne();
}
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static String getMemberOne() {
return singleton.getMemberOne();
}
#Override
public String getMemberOne() {
// codes that read file.
}
}
We extract all the method to AppProperties, and static instance in FileReader now using AppProperties.
Step 3. Static setter
public class FileReader implements AppProperties {
private static AppProperties singleton = new FileReader();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
...
...
}
We opened a seam in FileReader. By doing this, we can set change underlying instance in FileReader and it would never notice.
Step 4. Clean up
Now FileReader have two responsibilities. One is read files and provide result, another one is provide a global reference for system.
We can separate them and give them a good naming. Here is the result :
// This is the original FileReader,
// now is a AppProperties subclass which read properties from file.
public FileAppProperties implements AppProperties {
// implementation.
}
// This is the class that provide static methods.
public class GlobalAppProperties {
private static AppProperties singleton = new FileAppProperties();
public static void setAppProperties(AppProperties prop) {
singleton = prop;
}
public static String getMemberOne() {
return singleton.getMemberOne();
}
...
...
}
END.
After this refactoring, whenever you want to test. You can set a mock AppProperties to GlobalAppProperties
I think this refactoring would be better if all you want to do is break the same global dependency in many classes.
Powermock core provides a convenient utility method that could be used for this purpose.
Add powermock-core to your project.
testImplementation group: 'org.powermock', name: 'powermock-core', version: '2.0.9'
FileReader fileReader = mock(FileReader.class);
Whitebox.setInternalState(ClassToMock.class, "MEMBER_1", fileReader);
Whitebox.setInternalState is just a convenient method to set the value of a field using reflection. So it could be used along with any Mockito tests.
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.
I am trying to unit test an action filter I wrote. I want to mock the HttpClientCertificate but when I use MOQ I get exception. HttpClientCertificate doesnt have a public default constructor.
code:
//Stub HttpClientCertificate </br>
var certMock = new Mock<HttpClientCertificate>();
HttpClientCertificate clientCertificate = certMock.Object;
requestMock.Setup(b => b.ClientCertificate).Returns(clientCertificate);
certMock.Setup(b => b.Certificate).Returns(new Byte[] { });
This is the most awkward case of creating unit testable systems in .NET. I invariable end up adding a layer of abstraction over the component that I can't mock. Normally this is required for classes with inaccessible constructors (like this case), non-virtual methods or extension methods.
Here is the pattern I use (which I think is Adapter pattern) and is similar to what MVC team has done with all the RequestBase/ResponseBase classes to make them unit testable.
//Here is the original HttpClientCertificate class
//Not actual class, rather generated from metadata in Visual Studio
public class HttpClientCertificate : NameValueCollection {
public byte[] BinaryIssuer { get; }
public int CertEncoding { get; }
//other methods
//...
}
public class HttpClientCertificateBase {
private HttpClientCertificate m_cert;
public HttpClientCertificateBase(HttpClientCertificate cert) {
m_cert = cert;
}
public virtual byte[] BinaryIssuer { get{return m_cert.BinaryIssuer;} }
public virtual int CertEncoding { get{return m_cert.CertEncoding;} }
//other methods
//...
}
public class TestClass {
[TestMethod]
public void Test() {
//we can pass null as constructor argument, since the mocked class will never use it and mock methods will be called instead
var certMock = new Mock<HttpClientCertificate>(null);
certMock.Setup(cert=>cert.BinaryIssuer).Returns(new byte[1]);
}
}
In your code that uses HttpClientCertificate you instead use HttpClientCertificateBase, which you can instantiate like this - new HttpClientCertificateBase(httpClientCertificateInstance). This way you are creating a test surface for you to plug in mock objects.
The issue is that you need to specify constructor parameters when creating the mock of the HttpClientCertificate.
var certMock = new Mock<HttpClientCertificate>(ctorArgument);
The bad news is that the ctor for HttpClientCertificate is internal and takes in an HttpContext, so it probably won't work.
Unless you want to write more code to make the class "Testable" I suggest you use Typemock Isolator, Unless specified otherwise it looks for the first c'tor available - public, internal or private and fake (mocks) it's parameters so you won't have to.
Creating the fake object is as simple as:
var fakeHttpClientCertificate = Isolate.Fake.Instance<HttpClientCertificate>();
Another alternative is to use the free Microsoft Moles framework. It will allow you to replace any .NET method with your own delegate. Check out the link as it gives an example that is pretty easy to understand. I think you'll find it much nicer than adding layers of indirection to get HttpClientCertificate into a testable state.
I've got a class with one public method and many private methods which are run depending on what parameter are passed to the public method so my code looks something like:
public class SomeComplexClass
{
IRepository _repository;
public SomeComplexClass()
this(new Repository())
{
}
public SomeComplexClass(IRepository repository)
{
_repository = repository;
}
public List<int> SomeComplexCalcualation(int option)
{
var list = new List<int>();
if (option == 1)
list = CalculateOptionOne();
else if (option == 2)
list = CalculateOptionTwo();
else if (option == 3)
list = CalculateOptionThree();
else if (option == 4)
list = CalculateOptionFour();
else if (option == 5)
list = CalculateOptionFive();
return list;
}
private List<int> CalculateOptionOne()
{
// Some calculation
}
private List<int> CalculateOptionTwo()
{
// Some calculation
}
private List<int> CalculateOptionThree()
{
// Some calculation
}
private List<int> CalculateOptionFour()
{
// Some calculation
}
private List<int> CalculateOptionFive()
{
// Some calculation
}
}
I've thought of a few ways to test this class but all of them seem overly complex or expose the methods more than I would like. The options so far are:
Set all the private methods to internal and use [assembly: InternalsVisibleTo()]
Separate out all the private methods into a separate class and create an interface.
Make all the methods virtual and in my tests create a new class that inherits from this class and override the methods.
Are there any other options for testing the above class that would be better that what I've listed?
If you would pick one of the ones I've listed can you explain why?
Thanks
You don't need to change your interface to test these methods. Simply test the public interface thoroughly to ensure that all the private methods are tested:
void Test1()
{
new SomeComplexClass(foo).SomeComplexCalcualation(1);
}
void Test2()
{
new SomeComplexClass(foo).SomeComplexCalcualation(2);
}
and so on...
You can use a coverage tool (e.g. NCover for .NET) to ensure that all the code you wanted to test has actually been tested.
How about OptionCalculators, to which the original class dispatches the work? Each would have just one method, CalculateOption, and of course it would be public, and therefore readily testable.
You should only need to test the public methods of the Class/Interface.
You just need to be sure you have enough Unit test cases to thoroughly test all the different behaviors of those public methods (which would excersise the private methods appropriately).
If each of those computations is that complex, is each one really a single method? If those computations share code, or should be multiple methods each, it's an argument for the interface/Strategy approach you mention, so you can test each of those steps.
Another thing to consider: thoroughly exercising the one public method is testing two things
a) that the ComputeOptionN code is working, AND
b) that the option checking is working properly.
Not a problem if you're literally passing in ints, but not ideal, especially if the comparison could ever get more complicated, or if it might change around.
#Carl is right. This is nothing more than utilizing a strategy pattern. Store all the calculators in an array inject the array into SomeComplexClass. This will allow you to unit test each calculator by itself and the SomeComplexClass. Now you can do this:
public List<int> SomeComplexCalcualation(int option)
{
return calculator.find(option);
}
Very easy to mock calculator