Let's see some advanced topics about mORMot's mocking and stubbing features:
- How to handle complex values in parameters / arguments or results, like
record
; - Stubbing via a custom delegate or callback;
- Calls tracing.
2012-10-14
2012-10-14. Open Source › mORMot Framework
Let's see some advanced topics about mORMot's mocking and stubbing features:
record
;2012-10-14. Open Source › mORMot Framework
In order to fulfill the SOLID principles, two features are to be available when handling interfaces:
We will show now how mORMot provides all needed features for such patterns, testing a simple "forgot my password" scenario: a password shall be computed for a given user name, then transmitted via SMS, and its record shall be updated in the database.
2012-10-14. Open Source › mORMot Framework
Our mORMot framework is now able to
stub or mock any Delphi interface
.
As usual, the best way to explain what a library does is to look at the code
using it.
Here is an example (similar to the one shipped with RhinoMocks) of
verifying that when we execute the "forgot my password" scenario, we remembered
to call the Save()
method properly:
procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; begin TInterfaceStub.Create(TypeInfo(ISmsSender),SmsSender). Returns('Send',[true]); TInterfaceMock.Create(TypeInfo(IUserRepository),UserRepository,self). ExpectsCount('Save',qoEqualTo,1); with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; end;
And... that's all, since the verification will take place when
IUserRepository
instance will be release.
If you want to follow the "test spy" pattern (i.e. no expectation defined a priori, but manual check after the execution), you can use:
procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; Spy: TInterfaceMockSpy; begin TInterfaceStub.Create(TypeInfo(ISmsSender),SmsSender). Returns('Send',[true]); Spy := TInterfaceMockSpy.Create(TypeInfo(IUserRepository),UserRepository,self); with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; Spy.Verify('Save'); end;
This is something unique with our library: you can decide if you want to use
the classic "expect-run-verify" pattern, or the somewhat more direct
"run-verify" / "test spy" pattern.
With mORMot, you pick up your mocking class (either
TInterfaceMock
or TInterfaceMockSpy
), then use it as
intended. You can even mix the two aspects in the same instance! It is just a
matter of taste and opportunity for you to use the right pattern.
2012-07-26
2012-07-26. Open Source › mORMot Framework
As stated during our
recent benchmarks, the default SQlite3 write speed is quite slow,
when running on a normal hard drive. By default, the engine will pause after
issuing a OS-level write command. This guarantees that the data is written to
the disk, and features the ACID
properties of the database
engine.
ACID
is an acronym for "Atomicity Consistency Isolation
Durability" properties, which guarantee that database transactions are
processed reliably: for instance, in case of a power loss or hardware failure,
the data will be saved on disk in a consistent way, with no potential loss of
data.
You can overwrite this default behavior by setting the
TSQLDataBase.Synchronous
property to smOff
instead of
the default smFull
setting. When Synchronous
is set
to smOff
, SQLite continues without syncing as soon as it
has handed data off to the operating system. If the application running
SQLite crashes, the data will be safe, but the database might become
corrupted if the operating system crashes or the computer loses power before
that data has been written to the disk surface. On the other hand, some
operations are as much as 50 or more times faster with this setting.
When the same tests are performed with Synchronous :=
smOff
, "Write one" speed is enhanced from 8-9 rows per second into about
400 rows per second, on a physical hard drive (SSD or NAS drives may not suffer
from this delay). We'll show below the detailed benchmark results.
So depending on your application requirements, you may switch Synchronous setting to off, to enhance server-side responsiveness.
2012-07-12
2012-07-12. Open Source › mORMot Framework
If you discovered the mORMot framework, you may have found out that its implementation may sound restricted, in comparison to other ORMs, due to its design. It would be easy to answer that "it is not a bug, it is a feature", but I suspect it is worth a dedicated article.
Some common (and founded) criticisms are the following (quoting from our
forum - see e.g. this
question):
- "One of the things I don't like so much about your approach to the ORM is the
mis-use of existing Delphi constructs like "index n
" attribute for
the maximum length of a string-property. Other ORMs solve this i.e. with
official Class
-attributes";
- "You have to inherit from TSQLRecord
, and can't persist any
plain class";
- "There is no way to easily map an existing complex database".
I understand very well those concerns.
Our mORMot framework is not meant to fit any purpose, but it is worth
understanding why it has been implemented as such, and why it may be quite
unique within the family of ORMs - which almost all are following the
Hibernate way of doing.
2012-05-25
2012-05-25. Open Source › mORMot Framework
With a previous article, we introduced the concept of "Domain-Driven design" into our framework presentation.
It's now time to detail a bit more this very nice software architecture design, and how mORMot is able to achieve such an implementation pattern.
2012-05-20
2012-05-20. Pascal Programming
In a Stack Overflow question, someone asked about some nested procedure call he found out. That is, a procedure inside another procedure.
He found out this coding style to be messy, which sounds like a reasonable opinion. But his alternative proposal of putting the internal procedure outside the main one, i.e. making it global, is IMHO even worse.
In some case, a private class
, or even record
or object
with methods is an handy and maintainable implementation
pattern.
2012-05-03
2012-05-03. Open Source › mORMot Framework
By default, during interface-based service call,
any record
parameter or function result will be serialized with
our proprietary binary (and optimized layout) - i.e. RecordLoad
and RecordSave
functions - then encoded in Base-64, to be
stored as plain text within the JSON stream.
But custom record JSON serialization can be defined, as with any
class
- see this article - or
dynamic array - see this
article.
2012-04-25
2012-04-25. Open Source › mORMot Framework
In a discussion with Henrick Hellström, in Embarcadero forums, I wrote some high-level information about mORMot.
It was clear to me that our little mORMot is now far away from a simple Client-Server solution.
The Henrick point was that with Real Thin Client (RTC), you are able to write any Client-Server solution, even a RESTful / JSON based one.
He is of course right, but it made clear to me all the work done in
mORMot since its beginning.
From a Client-Server ORM, it is now a complete SOA framework, ready to serve
Domain-Driven-Design solutions.
2012-02-29
2012-02-29. Pascal Programming
No, interface(-book) is not another social network, sorry.
In Delphi OOP model, an interface defines a type that comprises
abstract virtual methods.
The short, easy definition is that an interface is a declaration of
functionality without an implementation of that functionality. It defines
"what" is available, not "how" it is made available. This is the so called
"abstraction" benefit of interfaces (there are another benefits, like
orthogonality of interfaces to classes, but we'll see it later).
In its upcoming 1.16 revision, our mORMot framework is able to use interface for its service definition.
So we'll discuss and introduce this gem available in all modern languages - including Delphi: interfaces.
2011-12-30
2011-12-30. Open Source › mORMot Framework
A variety of programming languages suffer from a denial-of-service (DoS) condition against storage functions of key/value pairs in hash data structures, the condition can be leveraged by exploiting predictable collisions in the underlying hashing algorithms.
The issue finds particular exposure in web server applications and/or frameworks. In particular, the lack of sufficient limits for the number of parameters in POST requests in conjunction with the predictable collision properties in the hashing functions of the underlying languages can render web applications vulnerable to the DoS condition. The attacker, using specially crafted HTTP requests, can lead to a 100% of CPU usage which can last up to several hours depending on the targeted application and server performance, the amplification effect is considerable and requires little bandwidth and time on the attacker side.
Source: #2011-003 multiple implementations denial-of-service via hash algorithm collision
2011-12-11
2011-12-11. Pascal Programming
To my understanding, the so-called "strong-typing" feature is one big benefit of the Delphi object pascal language.
As stated by wikipedia:
Most generally, "strong typing" implies that the programming language places severe restrictions on the intermixing that is permitted to occur, preventing the compiling or running of source code which uses data in what is considered to be an invalid way. For instance, an addition operation may not be used with an integer and string values; a procedure which operates upon linked lists may not be used upon numbers. However, the nature and strength of these restrictions is highly variable.
Some Delphi users may find this is a limitation of the language, in
comparison with other "fashionable" script idioms (like Python, Javascript of
Ruby). For me, runtime strong typing (alla Python or Ruby) is not true strong
typing. Simon Stuart just
proposed a smartstring
kind of string, which is in fact a
weakstring
type. As far as I understood his point, he wanted to
get rid of all the warnings emitted by Unicode-version of the Delphi compiler,
about explicit string
conversion.
In fact, I use to go in the opposite direction. For wide projects, strong-typing is one of the big benefit of using Delphi (like other main "serious" languages like Java, C, C++, Ada or C#).
2011-12-08
2011-12-08. Pascal Programming
Among all trolling subject in forums, you'll find out the great Garbage Collection theme.
Fashion languages rely on it. At the core of the .Net and Java framework, and all scripting languages (like JavaScript, Perl, Python or Ruby), you'll find a Garbage Collector. New developers, just released from schools, do learn about handling memory only in theory, and just can't understand how is memory allocated - we all have seen such rookies involved in Delphi code maintenance, leaking memory as much as they type. In fact, most of them did not understood how a computer works. I warned you this will be a trolling subject.
And, in Delphi, there is no such collector. We handle memory in several ways:
class
or globally;class
instances allocated on heap - in
at least three ways: with a try..finally Free
block, with a
TComponent
ownership model in the VCL, or by using
an interface
(which creates an hidden try..finally
Free
block);string
, array
of
, interface
or variant
kind of
variables.It is a bit complex, but it is also deadly powerful. You have several memory allocation models at hand, which can be very handy if you want to tune your performance and let program scale. Just like manual recycling at home will save the planet. Some programmers will tell you that it's a waste of cell brain, typing and time. Linux kernel gurus would not say so, I'm afraid.
Then came the big Apple company, which presented its new ARC model (introduced in Mac OS X 10.7 Lion) as a huge benefit for Objective-C in comparison with the Garbage Collection model. And let's face it: this ARC just sounds like the Delphi memory model.
2011-11-27
2011-11-27. Pascal Programming
Delphi is sometimes assimilated to a RAD product - and this is a marketing
label - but IMHO Delphi is much more than RAD.
With Delphi, you can make very serious and clean programming.
Including SOLID style of coding.
The acronym SOLID is derived from the following OOP principles (quoted from the corresponding Wikipedia article):
If you have some programming skills, those principles are general statements you may already found out by yourself. If you start doing serious object-oriented coding, those principles are best-practice guidelines you would gain following.
They certainly help to fight the three main code weaknesses:
2011-08-28
2011-08-28. Pascal Programming
Writing working multi-threaded code is not easy - it's even hard, as as a Delphi expert just wrote in his blog.
In fact, the first step into multi-thread application development could be:
"protect your shared variables with locks (aka critical sections), because you are not sure that the data you read/write is the same for all threads".
The CPU per-core cache is just one of the possible issues, which will lead into reading wrong values. Another issue which may lead into race condition is two threads writing to a resource at the same time: it's impossible to know which value will be stored afterward.
2011-08-20
2011-08-20. Open Source › Open Source libraries
We already shipped a sophisticated set of logging classes some month ago.
Since then, its features have been enhanced, and the system has been deeply interfaced with our main ORM framework. Now almost all low-level or high-level operations can be logged on request.
But since the log files tend to be huge (for instance, if you set the logging for our unitary tests, the 6,000,000 unitary tests creates a 280 MB log file), a log viewer was definitively in need.
2011-07-02
2011-07-02. Open Source › mORMot Framework
There is a well known syndrome around, against ORM.
Do you remember The Vietnam of Computer Science article?
It is worth reading... and commenting.
Sounds a bit outdated by now. Tempus fugit!
2011-06-16
2011-06-16. Pascal Programming
After a question on StackOverflow, I wanted to comment about the speed of generated code by diverse Delphi compiler versions.
Since performance matters when we write general purpose libraries like ours, we have some feedback to propose:
2011-06-01
2011-06-01. Open Source › mORMot Framework
According to the n-Tier architecture, data filtering and validation should be implemented in the business logic, not in the User Interface.
If you were used to develop RAD database application using Delphi, you may have to change a bit your habits here. Data filtering and validation should be implemented not in the User Interface, but in pure Delphi code.
Data filtering is a process run on the User entry: for instance, it will
trim left or right spaces, make the text uppercase...
Data validating is performed before saving the data to the database: for
instance, an email address is checked for consistency, a field value to be
unique...
Some try to implement this using an external
scripting engine, in a procedure/event mode. Back to the 80th...
In our ORM framework, filtering and validation can be performed by creating
some Delphi classes, which may be used on both Server and Client side.
2011-05-24
2011-05-24. Open Source › mORMot Framework
Commonly, it can be achieved, in the SOA over HTTP world via:
- HTTP basic auth over HTTPS;
- Cookies and session management;
- Query Authentication with additional signature parameters.
We'll have to adapt, or even better mix those techniques, to match our framework architecture at best.
Each authentication scheme has its own PROs and CONs, depending on the purpose of your security policy and software architecture.
« previous entries - page 4 of 5 - next entries »