Problem with querySim

Hi, I’m new to using testbox.

This is my function

component extends=“testbox.system.BaseSpec” {

function beforeAll(){
mockAccounts = createMock(“cfc.Accounts”);

}

function run(){
describe(“Suite 1 for Query”,function(){
it(“Simple Query Test”,function(){

mockQuery = querySim("[AccountId],[User Name]

0001|John Smith

0002| Mihir Palakurthi");

//results = mockAccounts.GetId(0001); // When I run these two lines I get an error datasource [xxxxx] doesn’t exist.

//expect(results).toBe(0001);

mockAccounts.$(method = “GetId”,preserveReturnType=‘false’); // I did this because the functions return type is string and not query

results = mockAccounts.GetId(0001); // when I run these lines I get an error variable [RESULTS] doesn’t exist.

expect(results).toBe(0001);

});

});

}

}

Is this the correct way of doing things ?

Hi Mihr, what are you trying to do here in this test? You’ve created a mock object, mocked a method on that object (which doesn’t return anything and then called that mocked method (which as you observed, doesn’t return anything).

If your purpose is to test the getID() method, then don’t mock the method itself, mock the dependencies of that method (like your datasource). Without being able to see your code I can only guess at what it does. If you have cfquerys embedded right inside your getID() method, then you’re going to have a hard time doing unit testing since you haven’t abstracted your DAO logic away. if Accounts is a DAO, then I’d question whether you need to test it at all.

let’s assume your getID() call does something like so:

function getID( foo ) {
var myData = accessDBHere();
// Perform business logic on data here
return something;
}

In the case above, you have your actual DAO abstracted out to the accessDBHere() method call, so you would mock just that method to return your fake query and then you would built your expectations based on whether the return value was correct. If all the method does is hit the DB and return the result, I wouldn’t bother unit testing this at all since there’s really no business logic in that so it’s just an empty test. This is better suited to an integration test, but that depends on whether you’re using a framework like ColdBox that has the actual plumbing in place for integration testing.

Hi Brad,

So this is my function that I’m trying to test. I starting with this as just a simple sample test (it may not require testing but I’m just trying to start with something simple so I can get a feel for how to do things correctly). Like you said I’m trying to test the method getID.

select AccountId, User Name where AccountId = '#AccountId#'

<cfreturn “#ExistingId#”>

So, I’m pretty sure it’s safe to assume what ever I did was wrong. Also Accounts is not a DAO.

Thanks for posting the code. I know you didn't request a code review, but
there's several things in there worth addressing:

   - Var scoping issues on your query name. You're leaking
   *getExistingIDAssociation* into your CFC's variables scope. Either var
   it above, or do *local.getExistingIDAssociation*
   - Please use cfquery param in your query. Your current query is
   potentially unsafe and might not be using a re-usable execution plan
   - What is the purpose of the cfloop since it sets the same variable in
   each iteration? If the query only returns one record, just use it. If it
   returns more than one, that seems like a bug.
   - Don't wrap a variable both in pound signs and then quotes. They
   cancel themselves out and waste keystrokes. You just need <cfreturn
   >

So on to your question of how to test this-- The real answer is there is
nothing to test here. All you're really doing is running a query and
returning the value of a column in the result. There's no business logic,
no transformations, and no internal state mutation.

So, you want to test it anyway just to learn? No problem. As it stands,
this function cannot be unit tested the way it is written. That's because
you have not encapsulated your data access into a DAO (or just another
method). Unit tests are supposed just run the code inside the method (SUT,
or software under test) and nothing else. The only way to really unit
tests this would be to move the query to another method, then mock that
method to return the fake query (like I showed before). There's no way to
mock an inline cfquery like that. Of course, at that point, this method
would literally be pointless because it doesn't do anything other than
running the query and returning the value so it's sort of a poor example.

There is another kind of testing called integration testing. It is where
you run the entire request from top to bottom and your expectations based
on the outward things a user would see in the browser. For example, run
this page and confirm that the user is logged in and redirected to their
profile. This sort of testing does not typically mock anything and runs
all DB calls. If you're using ColdBox, we can help you implement
integration tests.

Thanks!

~Brad

*Developer Advocate*
*Ortus Solutions, Corp *

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Hi Brad,

Thank you very much for the help, you made things a lot more clear for me.

I do have a couple of questions though(not in regard with the function I asked in this post).

  1. You said in your initial response that I should mock dependencies of the function, so how would I mock a data source or if there is a stored proc would I just mock query the result of the stored proc?

  2. Was wondering if you could point me towards some documentation regarding the integration testing.

Thanks,

Sorry I didn't reply last week-- I was traveling and missed your message.

*> how would I mock a data source *

You don't. This is why you abstract your data access into a DAO so it can
be mocked as a function call. ColdFusion provides no way to mock a
datasource in a cfquery tag that's inline with your business logic.
Separate testable business logic and data access into two different
layers. So when you want data, don't put a cfquery, inject your DAO and
call a method on that DAO to get the data. Now you can easily mock the
entire DAO in your service to return a fake result set.

*> point me towards some documentation regarding the integration testing*

Are you using ColdBox MVC? If not, you basically can't do integration
testing. No other CF framework has the plumbing for it. If you are using
ColdBox, I'd start with the docs:

https://coldbox.ortusbooks.com/content/full/testing/integration_testing/

Thanks!

~Brad

*Developer Advocate*
*Ortus Solutions, Corp *

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com