MockBox – Mocking a Super Class

I’m getting my hands dirty using MXUnit Testing w/ MockBox recently. The basics where fairly easy to pickup, but I’ve now hit a road block. Lets say I need to test this method:

<cfcomponent extends="message" output="false">
    <cffunction name="send" access="public" returntype="void" output="false">
        <cfargument name="name" type="string" required="true">
        <cfif name neq "test">
            <cfset super.send(name=arguments.name)>
        </cfif>
    </cffunction>
</cfcomponent>

So following unit test ideology, I should just test what’s happening in this method and not attached methods.  If I had instantiated an object or the method was in the some component I could just mock the method being called. However since the method is located in the component’s parent, this does not appear to be working. The test contains:

variables.mockBox = new mockbox.MockBox();
variables.component = CreateObject('component', 'thisComponent');
variables.mockBox.prepareMock(variables.component);
variables.component.super.$('send');

This returns the error: “Expression: Element COMPONENT.SUPER is undefined in a Java object of type class [Ljava.lang.String; referenced as ””.

Now technically I could wrap the super.send call inside another local method and mock that method. However that would be coding for the test and would be worthless code and processor usage outside the test.

I’ve Googled this and searched ColdBox’s site for a solution to this, however I’m not getting anywhere.

Does anyone have any ideas or suggestions?

ColdFusion 9 Query of Query In CFScript

When doing a Query of Query using tag context you see:

<cfquery name="local.myQuery" dbtype="query">
SELECT *
FROM [local].myOtherQuery
WHERE Col1 = 'Chris'
</cfquery>

You would expect you could just do the same in CFScript under ColdFusion 9:

local.queryService = new query();
local.queryService.setName("myQuery");
local.queryService.setDBType("query");
local.objQueryResult = local.queryService.execute(sql="SELECT [Value] FROM [local].myOtherQuery WHERE Col1='Chris'");
local.queryResult= local.objQueryResult.getResult();

However this will produce an error:
coldfusion.sql.imq.imqException: Query Of Queries runtime error.
Table named local.myOtherQuery was not found in memory. The name is misspelled or the table is not defined.

Thanks to Jared Rypka-Hauer, I found a resolution to this lame error by using the setAttributes method:

local.queryService = new query();
local.queryService.setName("myQuery");
local.queryService.setDBType("query");
local.queryService.setAttributes(sourceQuery=local.myOtherQuery);
local.objQueryResult = local.queryService.execute(sql="SELECT [Value] FROM sourceQuery WHERE Col1='Chris'");
local.queryResult = local.objQueryResult.getResult();

This must be done because local.myOtherQuery is out of context at least until they release closures for ColdFusion.

If you would like to see the inner-works of this visit:
\CustomTags\com\adobe\coldfusion\query.cfc in your ColdFusion 9 install directory.

Update 7/7/2011:
Here’s an excellent blog from Ben Nadel also describing a solution to this issue:
http://www.bennadel.com/blog/2224-Performing-Query-Of-Queries-Using-ColdFusion-9-s-Query-cfc-Component.htm

Sending a Variable Dump in Cfscript Mail for ColdFusion 9

Recently I had an issue with a variable that I needed to take a look into. Many times I just mail myself a Cfdump of the variable. Today I tried it completely Cfscript-wise and failed with a “Method writeDump with 1 arguments is not in class coldfusion.runtime.CFComponent.” error. This is what I tried:

local.testVar = 'test';

local.mailerService = new mail();
local.mailerService.setTo('bogus@domain.xyz');
local.mailerService.setFrom('bogus@domain.xyz');
local.mailerService.setSubject('Heres your var dump');
local.mailerService.setType('html');
local.mailerService.send(body=writeDump(local.testVar));

I even tried writing it to a variable (assuming this would fail):

local.testVar = 'test';
local.testDump = writeDump(local.testVar);

local.mailerService = new mail();
local.mailerService.setTo('bogus@domain.xyz');
local.mailerService.setFrom('bogus@domain.xyz');
local.mailerService.setSubject('Heres your var dump');
local.mailerService.setType('html');
local.mailerService.send(body=local.testDump);

But that just failed with the same error on the second line above.

I really couldn’t find anything on this in Google, but after manipulating my keywords for awhile, I ran across a blog with a code sample that seems to accomplish what I needed. The key was to run “savecontent” as save the contents off into a variable:

local.testVar = 'test';
savecontent variable="local.testDump" {
writeDump(local.testVar)
}

local.mailerService = new mail();
local.mailerService.setTo('bogus@domain.xyz');
local.mailerService.setFrom('bogus@domain.xyz');
local.mailerService.setSubject('Heres your var dump');
local.mailerService.setType('html');
local.mailerService.send(body=local.testDump);

Now before you say why would I dump a string, I was actually trying to dump a query result.

On a side-note, feel free to come to the Nebraska ColdFusion Users Group tonight and learn neat things like this!

Query Of Queries syntax error. Encountered “local.

If you’ve encountered an error “Query Of Queries syntax error. Encountered “local.” while running a Query of a Query in ColdFusion, thanks to Ben Nadel I have the solution.

<cfquery name="local.myQuery" dbtype="query">
SELECT [value]
FROM local.myQueryResults
WHERE [name] = 'Chris'
</cfquery>

Running the above code will error out due to “local” being a reserved keyword in SQL. The solution is to wrap “local” in brackets like “[local]”.

<cfquery name="local.myQuery" dbtype="query">
SELECT [value]
FROM [local].myQueryResults
WHERE [name] = 'Chris'
</cfquery>

Returning IDENTITY ID via ColdFusion 9’s CFQuery

Many of us are familiar with using:

SELECT @@IDENTITY AS ID

or in later versions of MSSQL:

SELECT SCOPE_IDENTITY() AS ID

in your SQL statement to return the last identity value that you just inserted into a SQL Table.

In ColdFusion 8 you could also use:

<cfquery datasource="#DSN#" result="myResult">
INSERT INTO MyTable (col1)
VALUES ('col1')
</cfquery>

<cfoutput>Inserted ID is: #myResult["IDENTITYCOL"]#</cfoutput>

(Use: IDENTITYCOL for SQL Server, ROWID for Oracle (is rowid not primary key), SYB_IDENTITY for Sybase, SERIAL_COL for Informix, GENERATED_KEY for MySQL)

However in ColdFusion 9 they standardized the variable name to GENERATEDKEY for all SQL environments.

<cfquery datasource="#DSN#" result="myResult">
INSERT INTO MyTable (col1)
VALUES ('col1')
</cfquery>

<!--- Tag based output --->
<cfoutput>Inserted ID is: #myResult["GENERATEDKEY"]#</cfoutput>
<!--- Script based output --->
insertedID = myResult.getPrefix().generatedkey

 

Managing Whitespace With CFC Output Attributes

A good rule of thumb inside a ColdFusion Component (CFC) is to set BOTH the output attributes of cfcomponent and cffunction to false.

<cfcomponent output="false">
    <cffunction name="foo" output="false">
    </cffunction>
</cfcomponent>

Normally I would think that the cffunction tag would inherit the output attribute and set its output attribute to false as well. However this is not the case.

The output attribute for cfcomponent only controls output in the constructor area, or everything outside of the functions. The output attribute for a function controls output only inside that function.

The other point to be aware of is if the output attribute is on, then any expression inside the pound(#) sign will be evaluated. If the output attribute is set to false then any expression inside a pound(#) sign will not be evaluated unless surrounded by a <cfoutput> tag. Rarely is there a need to use the pound(#) signs inside a function anyway unless it’s being evaluated in an attribute such as in <cfmail> or <cfswitch>. (See Mark Kruger’s blog on this)

Thanks to Ray Camden and O’Reilly’s Web Devcenter for enlightening me on this one.

Here’s another related article dealing with memory issues regarding use of the output attribute: http://wiki.mxunit.org/display/default/How+cfcomponent+output%3Dtrue++can+affect+memory+consumption

Turning New Lines Into HTML Line Breaks

Many times you need to process textarea field content in ColdFusion and add HTML line breaks so it actually displays correctly on screen or in an email. An easy way to accomplish this is to replace the character codes 10 and 13 with <br>:

Replace(textVar, "#Chr(10)##Chr(13)#", "<br>", "all")

This code takes:

Line 1
Line 2

Line 3

And turns it into:

Line 1<br>
Line 2<br>
<br>
Line 3

varScoper 1.30 CFBuilder v1 Issues

I just installed varScoper 1.30 CF Builder (version 1) extension on my machine, but found a few issues getting it to run.

  1. Make sure you put the varScoper folder in your Document Root you defined in your Server Settings. On mine this is the directory for my localhost.
  2. Modify the cfbuilder.cfm file, in the handlers directory, and add:
    <cfsetting showdebugoutput="false">
    

    to the beginning of the file. You may need to open NotePad with Administrative privileges I found out for some reason.

  3. It appears the “Description” window in the “Extensions” tab is broken for this extension. There is no fix as of right now.

Thanks to Ray Camden for the help on this.

ColdFusion Application.cfc Differences For This and Application Scope

Thanks to Ray Camden, I learned something new today that was of great help.

Inside the Application.cfc, I always assumed the “this” and “application” scopes where the same. This is incorrect.

“Application” scope will only store name/value pairs. It has no impact on how the application behaves on the server level (built-in behavior).

<cfset application.name = value>

While “this” scope is used to change the behavior of the application itself.  For example: defining custom tag paths and the common datasource name.

<cfset this.name= value>

Ternary Operator within ColdFusion 9

For the first time today I used ColdFusion’s new ternary operator. I learned about it last week as a alternative to the inline-IF (IIF()). No longer do I need to remember the quarks about the DE operator required in IIF.

A ternary operator takes three arguments: ((condition) ? trueStatement : falseStatement)

Example:

<tr class="#(currentrow mod 2) ? 'lightRow'  : 'darkRow'#">

This can also be done using inline if:

<tr class="#IIF(currentrow mod 2, DE('lightRow'), DE('darkRow')#">

Or using cfif:

<tr class="<cfif currentrow mod 2>lightRow<cfelse>darkRow</cfif>">

As you can see, you can use a simple inline operator without having to worry about IIF quirks or drawn out conditional statements. Remember this is introduced in ColdFusion 9.