3. The Model
Wirebox
Kickstarting Model Development
Unit Testing Model CFCs
Overview
4. The Model layer represents your data
structures and business logic. The domain-
specific representation of the information that
the application operates on.
A service layer approach is a way to architect
applications in which there is a layer that acts
as a service or mediator to your domain
models, data layers and so forth. This layer is
the one that event handlers can talk to in
order to interact with the domain model.
The Model - Reloaded
5. Last week, we looked at a data diagram
for our application and determined that
we‟re mostly focused on
“recommendation” table
We will create a “recommendationService”
and a “recommendationGateway” (and
later a “programGateway”
The Model - Reloaded
6. We also determined we will need to perform SELECT /
SAVE / DELETE functionality against this table
We can use “DataMgr” in out gateways stub this out
quickly, simply extend /common/model/basegateway
<cffunction name=“get”>
◦ <cfargument name=“id”>
◦ <cfreturn super.get(“recommendation”, arguments)>
</cffunction>
<cffunction name=“save”>
◦ <cfargument name=“data”>
◦ <cfreturn super.save(“recommendation”, arguments.data)>
</cffunction>
The Model - Reloaded
7. Wirebox allows us to quickly “inject”
dependencies into CFC‟s – generally with a
simple CFPROPERTY tag
◦ <cfcomponent>
<cfproperty name=“myGateway”
inject=“myGateway”>
◦ INSTEAD OF
<cfcomponent>
◦ <cffunction name=“init”>
<cfset myService=createObject(„component‟, „model.
myGateway‟).init(datasource=….)>
Wirebox
8. Wirebox also gives us access to many more
objects via its “DSL” (domain specific
language)
◦ <cfproperty name=“myDSN”
inject=“coldbox:datasource:main”>
◦ <cfproperty name=“logBox” inject=“logbox”>
◦ <cfproperty name=“HeaderText”
inject=“coldbox:setting:headerText”>
Wirebox
9. Wirebox is also an all-or-nothing
approach. If you start intermingling
auto-wire and non, you‟re probably asking
for trouble
Why bother?! Wirebox allows the
dependencies to be easily visible for a
given CFC and more importantly, when
unit testing, it allows us to “swap out”
objects (mocks, test objects, etc)
Wirebox
11. UNIT TESTING
◦ In computer programming, unit testing is a
procedure used to validate that individual
units of source code are working properly. A
unit is the smallest testable part of an
application. In procedural programming a unit
may be an individual
program, function, procedure etc, while in
object-oriented programming, the smallest unit
is always a Class; which may be a base/super
class, abstract class or derived/child class.
Wikipedia
MXUnit + Testing Model CFCs
12. It might be tedious and take time to get into the flow
of Test Driven Development. However, there are
incredible benefits to testing:
◦ Can improve code quality
◦ Quick error discovery
◦ Code confidence via immediate verification
◦ Can expose high coupling
◦ Encourages refactoring to produce testable code
◦ Testing is all about behavior and expectations
MXUnit + Testing Model CFCs
13. Functional testing relies on the action of
verification of specific requirements in our
software. This can usually be tracked via
use cases or Agile stories. "Can a user log
in?", "Does the logout work", "Can I
retrieve my password", "Can I purchase a
book?". Our main focus of functional
testing is that all these use cases need to
be met.
MXUnit + Testing Model CFCs
14. Non Functional Testing are testing aspects that
are not related to our specific requirements but
more of the quality of our software.
◦ Can our software scale?
◦ Is our software performant?
◦ Can it sustain load? What is the maximum load it can
sustain?
◦ What do we do to extend our security? Are our servers
secure?
MXUnit + Testing Model CFCs
15. Bugs Cost Money!!
MXUnit + Testing Model CFCs
16. Static testing relies on human interaction not only with our code
but with our developers and stakeholders. Some aspects can be
code reviews, ui walkthroughs, design and modeling
sessions, etc.
Through experience, we can also attest that static testing is
sometimes omitted or considered to be a waste of time.
Especially when you need to hold up on production releases to
review somebody else‟s work.
Not only that, but sometimes code reviews can spark animosity
between developers and architects as most of the time the idea is
to find holes in code, so careful tact must be in place and also
maturity across development environments. In true fun we can
say: “Come on, take the criticism, it is for the common good!”
MXUnit + Testing Model CFCs
17. On the other side of the spectrum, dynamic testing relies on the fact of executing
test cases to verify software. Most of the time it can be the developers themselves or
a QA team than can direct testing cases on executed code.
Unit Testing - We should be testing all the CFCs we create in our applications.
Especially when dealing with Object Oriented systems, we need to have mocking and
stubbing capabilities (See MockBox).
Integration Testing - Unit tests can only expose issues at the CFC level, but what
happens when we put everything together? Integration testing in ColdBox allows you
to test requests just like if they where executed from the browser. So all your
application loads, interceptions, caching, dependency injection, ORM, database, etc.
UI Integration Testing - Testing verification via the UI using tools like Selenium is
another great idea!
Load Testing - There are tons of free load testing tools and they are easy to test
how our code behaves under load. Don't open a browser with 5 tabs on it and start
hitting enter! We have been there and it don't work that great :)
MXUnit + Testing Model CFCs
18. Testing Vocabulary
◦ Test Plan: A test plan documents the strategy that will be used to verify and
ensures that a product or system meets its design specifications and other
requirements.
◦ Test Case: A set of conditions or variables under which a tester will determine
whether an application or software system is working correctly or not. In our
ColdFusion space, it might be represented by an MXUnit test case CFC.
◦ Test Script: A set of instructions that will be performed on the system under test
to test that the system functions as expected. This can be manual or automated.
Sometimes they can be called runners.
◦ Test Suite: A collection of test cases that are intended to be used to test a
software program to show that it has some specified set of behaviors or met
expectations.
◦ Test Data: A collection of pre-defined data or mocked data used to run against
our test cases
MXUnit + Testing Model CFCs
19. Testing Vocabulary
◦ Test Harness: A collection of software and test data configured to test a
program unit by running it under varying conditions and monitoring its behavior
and outputs.
◦ TDD: Test Driven Development - A software development process that relies on
the repetition of a very short development cycle: first the developer writes a
failing automated test case that defines a desired improvement or new
function, then produces code to pass that test and finally refactors the new code
to acceptable standards.
◦ Mock Object: Simulated objects that mimic the behavior of real objects in
controlled ways
◦ Stub Object: Simulated objects that have no behavior or implementations and
can be controlled and injected with functionality
◦ Assertions: The function to test if a predicate is true or false: X>1, 4=5
MXUnit + Testing Model CFCs
20. We‟ve seen MXUnit a LITTLE bit, but we‟ve
not begun to scratch the surface!
Coldbox offers us base unit tests which make
“setup” easier, and also add an enormous
amount of functionality
(mocking, stubbing, querySim, etc)
The MXUnit test runner in CFBuilder allows us
to develop / test without leaving the IDE!
MXUnit + Testing Model CFCs
21. We‟re going to begin by looking at
“baseModelTest”
Basic Setup
component extends="coldbox.system.testing.BaseModelTest"
model="myApp.model.User"{
function setup(){
super.setup();
user = model;
}
function testisActive(){
isActive = user.isActive();
Debug(isActive);
assertEquals( false, isActive);
}
}
MXUnit + Testing Model CFCs
23. Create a unit test CFCs
◦ app/test/unit/recommendation/recommendationGatewayTest.cfc
<cfcomponent name=“recommendationGatewayTest“
extends="coldbox.system.testing.BaseModelTest"model="ftf_bb.model.recommendation.reco
mmendationGateway">
<cffunction name="setUp">
<cfscript>
super.setup();
datasource=getMockDatasource(name='fixed_term_faculty');
model.$property(propertyName='datasource', mock=datasource);
this.myComp = model.init(datasource = datasource);
session.pid = '710917825';
</cfscript>
</cffunction>
</cfcomponent>
Next, add a test for “get”
<cffunction name=“testGet”>
<cfscript>
Results=this.myComp.get();
assertTrue(isQuery(results));
</cfscript>
</cffunction>
Assignment
24. Running this url in your browser should
show a failed test for testGet
◦ test/unit/recommendation/recommendationGatewayTest.cfc?method=runtestremote&output=h
tml
Create an accompanying model CFC
◦ App/model/recommendation/recommendationGateway.cfc
Assignment
25. And an accompanying model CFC
◦ App/model/recommendation/recommendationGateway.cfc
<cfcomponent name=“recommendationGateway”
extends=“/common/model/baseGateway_Autowire”>
◦ </cfcomponent>
Run test again – different error! This is because we‟re running the “abstract”
get method from baseGateway – lets define a concrete “get”
◦ <cffunction name=“get”>
<cfreturn super.get(“recommendation”)>
</cffunction>
Run test agan – SUCCESS! We just created our first testable model function!
Furthermore, we‟re selecting records from the db without any sql!
Assignment
26. Lets create a save test
<cffunction name=“testSave”>
<cfscript>
Data.fname=“test”;
Data.lname=“user”;
Data.pid=“123456”;
Results = This.mycomp.save(data);
assertTrue(isNumeric(results));
</cfscript>
</cffunction>
Run tests – FAIL!
Assignment
27. Lets create a save method
<cffunction name=“save”>
<cfargument name=“data”>
<cfscript>
return
super.save(“recommendation”, arguments.data);
</cfscript>
</cffunction>
Run tests – PASS!
Assignment
28. Lets create a delete test
<cffunction name=“testDelete”>
<cfscript>
This.mycomp.delete(id=1);
assertTrue(true);
</cfscript>
</cffunction>
Run tests – FAIL!
Assignment
30. We‟ve just created a gateway CFC to
handle very basic CRUD operations and
associated unit tests with less then 60
lines of code!
Next week, we‟ll create a service and start
consuming this gateway in our
recommendation.submission handler
SHAZAM!