One request that has come up frequently from users of the ColdFusion Koans was to have the ability to see the test results in order. This weekend I created a new test decorator that will allow users to do just that, set the order of the test results via annotation. Thinking it would be useful for others I opened a pull request on the MXUnit project and it was merged into the master branch on GitHub and added to the new 2.1.1 release.
In order to use the new decorator you must have MXUnit 2.1.1 or newer. One way to check if you have the required decorator is to look in the mxunit/framework/decorators directory for the file OrderdTestDecorator.cfc.
In order to set the order of your tests two things have to happen. The first is to add the custom decorator to you test component.
In a script based component the decorator is added like so:
In a tag based component you can add the decorator like this:
Once you have the annotation added to your test, you can start ordering them by adding the @order annotation to each test like so:
In a script based component the annotation looks like this:
In a tag based component it looks like this:
That's it, now your tests will run in the order you specified.
Showing posts with label Unit Testing. Show all posts
Showing posts with label Unit Testing. Show all posts
Monday, January 16, 2012
Monday, July 18, 2011
Mocking Java Objects In ColdFusion Unit Tests
I've been working on a project lately that has a few CFC's that rely heavily on a java object for much of their functionality. This was making my unit tests act more like functional tests since I was using the return values from the Java object to make my assertions. This didn't feel very good to me so I went to StackOverflow for some help. Edward Smith (Edward if you are reading this and would like me to link to something other than your stack overflow profile send me a comment and I'll update it) knocked it out of the park with his answer. I used what he said to implement the solution that this post is based off of. He mentioned that his company had used the Java mocking framework Mockito to mock Java objects in their ColdFusion unit tests. Brilliant! I already use Mockito for all of my Java unit tests, I just had never put it together that I could actually use it in my ColdFusion unit tests as well.
The first step in implementing this approach is to download the mockito jar file from http://www.mockito.org. For my implementation I'm using Mark Mandel's excellent JavaLoader project to create instances of java objects so I copy the jar into a lib folder in my application's root folder. Another approach would be to add the .jar file right to my ColdFusion server's instance, however I don't have any experience with this approach so I stuck with what I knew. This article on the Adobe blogs by Christian Cantrell might help you out if you'd rather use this approach.
Now that I have the .jar file in my project its time to make them available to my mxunit test. To do this I need to make them available to my test by loading them using JavaLoader and then to create an instance of the Mockto object so I can start mocking the Java objects. Its important to note that when using the JavaLoader approach you must also inititalize the .jar file of the object you mocking and ALL of the dependencies. Once the JavaLoader object is initialized with all of .jar files our objects need we need to create an instance of the mockito class for our test to use:
The next step is to create our mock Java objects. Since the component I'm trying to test is more or less a ColdFusion implementation of the java object I decided to recreate the mock before every test so I knew I was working with a clean copy of the mock. This means that I placed my mock code in my unit test's "setUp" method like so:
The syntax for creating a mock object in Mockito is pretty simple: variables.mockito.mock(variables.classLoader.create("com.sudios714.cfevernote.CFEvernote").init("123","S1","232","sandbox.evernote.com","mock").getClass()); Here I am calling the "mock" method on my Mockito object. The first parameter to the mock method is a Java class. In order to get a class I'm using the JavaLoader object's create method to create a new instance of a Java class and calling the getClass() method on that class to get the actual Java class to pass into Mockito. The last step is to inject it into my component. Now we have a working mock object injected into my component lets take a look at a test that puts my mock to use:
There are a few important things to note here. First is that the data that I'm creating for my mock is using a native Java object, in this case java.util.ArrayList. Since this is a part of the core Java language I don't need to use the JavaLoader to create an object for this data type. The next step is to do the actual mocking behavior. The statement variables.mockito.when(mockCFEvernote.listNotebooks(12)).thenReturn(retArray); is telling Mockito WHEN the listNotebooks method is called with a parameter of 12 to RETURN retArray which is the java.util.ArrayList object we created above.
Mockito can also be used to verify behavior, however this comes with a large caveat. Even if the verify statement is surrounded a try/catch statement (at least in my Win64/IIS7/CF9/Java 6 environment) if the verify statement fails, meaning that the method was not called with the expected parameter, the server will throw a 500 error. If the behavior verifies OK the test will run as expected. Knowing this if you'd still like to verify some behavior it can be accomplished by writing a verify statement like so: variables.mockito.verify(mockCFEvernote).listNotebooks(12); Here we are telling Mockito to verify that in the mockEvernote object the listNotebooks() method was called with a parameter of 12.
The first step in implementing this approach is to download the mockito jar file from http://www.mockito.org. For my implementation I'm using Mark Mandel's excellent JavaLoader project to create instances of java objects so I copy the jar into a lib folder in my application's root folder. Another approach would be to add the .jar file right to my ColdFusion server's instance, however I don't have any experience with this approach so I stuck with what I knew. This article on the Adobe blogs by Christian Cantrell might help you out if you'd rather use this approach.
Now that I have the .jar file in my project its time to make them available to my mxunit test. To do this I need to make them available to my test by loading them using JavaLoader and then to create an instance of the Mockto object so I can start mocking the Java objects. Its important to note that when using the JavaLoader approach you must also inititalize the .jar file of the object you mocking and ALL of the dependencies. Once the JavaLoader object is initialized with all of .jar files our objects need we need to create an instance of the mockito class for our test to use:
The next step is to create our mock Java objects. Since the component I'm trying to test is more or less a ColdFusion implementation of the java object I decided to recreate the mock before every test so I knew I was working with a clean copy of the mock. This means that I placed my mock code in my unit test's "setUp" method like so:
The syntax for creating a mock object in Mockito is pretty simple: variables.mockito.mock(variables.classLoader.create("com.sudios714.cfevernote.CFEvernote").init("123","S1","232","sandbox.evernote.com","mock").getClass()); Here I am calling the "mock" method on my Mockito object. The first parameter to the mock method is a Java class. In order to get a class I'm using the JavaLoader object's create method to create a new instance of a Java class and calling the getClass() method on that class to get the actual Java class to pass into Mockito. The last step is to inject it into my component. Now we have a working mock object injected into my component lets take a look at a test that puts my mock to use:
There are a few important things to note here. First is that the data that I'm creating for my mock is using a native Java object, in this case java.util.ArrayList. Since this is a part of the core Java language I don't need to use the JavaLoader to create an object for this data type. The next step is to do the actual mocking behavior. The statement variables.mockito.when(mockCFEvernote.listNotebooks(12)).thenReturn(retArray); is telling Mockito WHEN the listNotebooks method is called with a parameter of 12 to RETURN retArray which is the java.util.ArrayList object we created above.
Mockito can also be used to verify behavior, however this comes with a large caveat. Even if the verify statement is surrounded a try/catch statement (at least in my Win64/IIS7/CF9/Java 6 environment) if the verify statement fails, meaning that the method was not called with the expected parameter, the server will throw a 500 error. If the behavior verifies OK the test will run as expected. Knowing this if you'd still like to verify some behavior it can be accomplished by writing a verify statement like so: variables.mockito.verify(mockCFEvernote).listNotebooks(12); Here we are telling Mockito to verify that in the mockEvernote object the listNotebooks() method was called with a parameter of 12.
Labels:
ColdFusion,
Mockito,
MXUnit,
Unit Testing
Subscribe to:
Posts (Atom)