2. Integración de Spring con NHibernate
El marco Spring ofrece clases de utilidad para trabajar con el marco NHibernate. El uso de estas clases facilita la escritura del código de acceso a los datos de un SGBD. Consideremos la siguiente arquitectura multicapa:
![]() |
A continuación, vamos a construir una capa [dao] con [Spring / NHibernate], comentando el código de una solución funcional. No pretenderemos ofrecer todas las posibilidades de configuración o uso del marco [Spring / Nhibernate]. El lector podrá adaptar la solución propuesta a sus propios problemas con la ayuda de la documentación de Spring.NET [Spring.NET | Homepage ] (diciembre de 2011).
2.1. La capa de acceso a datos [dao]
![]() |
La base de datos es la base MySQL [dbpam_nhibernate] ya presentada en el apartado 1.2. La capa [dao] implementa la siguiente interfaz C#:
using Pam.Dao.Entites;
namespace Pam.Dao.Service {
public interface IPamDao {
// lista de todas las identidades de los empleados
Employe[] GetAllIdentitesEmployes();
// un empleado concreto con sus prestaciones
Employe GetEmploye(string ss);
// lista de todas las cotizaciones
Cotisations GetCotisations();
}
}
2.1.1. El proyecto de Visual Studio C# de la capa [dao]
El proyecto de Visual Studio de la capa [dao] es el siguiente:
![]() |
- En [1], el proyecto en su totalidad
- la carpeta [pam] contiene las clases del proyecto, así como la configuración de las entidades NHibernate
- los archivos [App.config] y [Dao.xml] configuran el framework Spring / NHibernate. Tendremos que describir el contenido de estos dos archivos.
- En [2], las diferentes clases del proyecto
- en la carpeta [entites] encontramos las entidades NHibernate estudiadas en el proyecto anterior (véase la página 14)
- en la carpeta [service], encontramos la interfaz [IPamDao] y su implementación con el framework Spring / NHibernate [PamDaoSpringNHibernate].
- La carpeta [tests] contiene las pruebas de la interfaz [IPamDao].
- En [3], las referencias del proyecto. La integración de Spring / NHibernate requiere nuevas DLL y [4].
En las referencias [3] del proyecto, se encuentran las siguientes DLL:
- NHibernate: para el ORM NHibernate
- MySql.Data: el controlador ADO.NET del SGBD MySQL 5
- Spring.Core: para el framework Spring, que se encarga de la integración de las capas
- log4net: una biblioteca de registros
- nunit.framework: una biblioteca de pruebas unitarias
- Spring.Aop, Spring.Data y Spring.Data.NHibernate32: garantizan la compatibilidad con Spring / NHibernate.
Nos aseguraremos de que todos estos DLL tengan su propiedad «Copia local» en True.
2.1.2. Configuración del proyecto C#
El proyecto está configurado de la siguiente manera:
![]() |
- en [1], el nombre del ensamblado del proyecto es [pam-dao-spring-nhibernate]. Este nombre aparece en varios archivos de configuración del proyecto.
2.1.3. Las entidades de la capa [dao]
![]() |
Las entidades (objetos) necesarias para la capa [dao] se han reunido en la carpeta [entites] [1] del proyecto. Estas entidades son las mismas que las del proyecto anterior (véase el apartado 1.3.2), con una diferencia que se encuentra en los archivos de configuración NHibernate. Tomemos, por ejemplo, el archivo [Employe.hbm.xml]:
- en [2], el archivo está configurado para incorporarse al ensamblado del proyecto
Su contenido es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Pam.Dao.Entites" assembly="pam-dao-spring-nhibernate">
<class name="Employe" table="EMPLOYES">
<id name="Id" column="ID">
<generator class="native" />
</id>
<version name="Version" column="VERSION"/>
<property name="SS" column="SS" length="15" not-null="true" unique="true"/>
<property name="Nom" column="NOM" length="30" not-null="true"/>
<property name="Prenom" column="PRENOM" length="20" not-null="true"/>
<property name="Adresse" column="ADRESSE" length="50" not-null="true" />
<property name="Ville" column="VILLE" length="30" not-null="true"/>
<property name="CodePostal" column="CP" length="5" not-null="true"/>
<many-to-one name="Indemnites" column="INDEMNITE_ID" cascade="all" lazy="false"/>
</class>
</hibernate-mapping>
- línea 3: el atributo «assembly» indica que el archivo [Employe.hbm.xml] se encontrará en el ensamblado [pam-dao-spring-nhibernate]
Por otra parte, en la carpeta [entites], encontramos una clase de excepción utilizada por el proyecto:
using System;
namespace Pam.Dao.Entites {
public class PamException : Exception {
// el código de error
public int Code { get; set; }
// fabricantes
public PamException() {
}
public PamException(int Code)
: base() {
this.Code = Code;
}
public PamException(string message, int Code)
: base(message) {
this.Code = Code;
}
public PamException(string message, Exception ex, int Code)
: base(message, ex) {
this.Code = Code;
}
}
}
La clase [PamException] se ha derivado de la clase [Exception] (línea 4) para añadirle un código de error (línea 7).
2.1.4. Configuración de Spring / NHibernate
Volvamos al proyecto de Visual C#:
![]() |
- En [1], los archivos [App.config] y [Dao.xml] configuran la integración Spring / NHibernate
2.1.4.1. El archivo [App.config]
El archivo [App.config] es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- secciones de configuración -->
<configSections>
<sectionGroup name="spring">
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
</sectionGroup>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
</configSections>
<!-- Configuración de Spring -->
<spring>
<parsers>
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
</parsers>
<context>
<resource uri="Dao.xml" />
</context>
</spring>
<!-- Esta sección contiene los ajustes de configuración de log4net -->
<!-- NOTE IMPORTANTE: los registros no están activos por defecto. Hay que activarlos mediante programación
avec l'instruction log4net.Config.XmlConfigurator.Configure();
! -->
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level %logger - %message%newline" />
</layout>
</appender>
<!-- Establecer el nivel de registro predeterminado en DEBUG -->
<root>
<level value="DEBUG" />
<appender-ref ref="ConsoleAppender" />
</root>
<!-- Configurar el registro para Spring. Los nombres de los registradores en Spring se corresponden con el espacio de nombres -->
<logger name="Spring">
<level value="INFO" />
</logger>
<logger name="Spring.Data">
<level value="DEBUG" />
</logger>
<logger name="NHibernate">
<level value="DEBUG" />
</logger>
</log4net>
</configuration>
El archivo [App.config] anterior configura Spring (líneas 5-9, 15-22) y log4net (línea 10, líneas 28-53), pero no NHibernate. Los objetos de Spring no se configuran en [App.config], sino en el archivo [Dao.xml] (línea 20). Por lo tanto, la configuración de Spring / NHibernate, que consiste en declarar objetos específicos de Spring, se encontrará en este archivo.
2.1.4.2. El archivo [Dao.xml]
El archivo [Dao.xml], que recoge los objetos gestionados por Spring, es el siguiente:
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net"
xmlns:db="http://www.springframework.net/database">
<!-- Referenciado por el archivo de configuración del contexto de la aplicación principal -->
<description>
Application Spring / NHibernate
</description>
<!-- Configuración de la base de datos y de NHibernate -->
<db:provider id="DbProvider"
provider="MySql.Data.MySqlClient"
connectionString="Server=localhost;Database=dbpam_nhibernate;Uid=root;Pwd=;"/>
<object id="NHibernateSessionFactory" type="Spring.Data.NHibernate.LocalSessionFactoryObject, Spring.Data.NHibernate32">
<property name="DbProvider" ref="DbProvider"/>
<property name="MappingAssemblies">
<list>
<value>pam-dao-spring-nhibernate</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="dialect" value="NHibernate.Dialect.MySQL5Dialect"/>
<entry key="hibernate.show_sql" value="false"/>
</dictionary>
</property>
<property name="ExposeTransactionAwareSessionFactory" value="true" />
</object>
<!-- gestor de transacciones -->
<object id="transactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate32">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="NHibernateSessionFactory"/>
</object>
<!-- Plantilla de Hibernate -->
<object id="HibernateTemplate" type="Spring.Data.NHibernate.Generic.HibernateTemplate">
<property name="SessionFactory" ref="NHibernateSessionFactory" />
<property name="TemplateFlushMode" value="Auto" />
<property name="CacheQueries" value="true" />
</object>
<!-- Objetos de acceso a datos -->
<object id="pamdao" type="Pam.Dao.Service.PamDaoSpringNHibernate, pam-dao-spring-nhibernate" init-method="init" destroy-method="destroy">
<property name="HibernateTemplate" ref="HibernateTemplate"/>
</object>
</objects>
- Las líneas 11-13 configuran la conexión a la base de datos [dbpam_nhibernate]. En ellas se encuentra:
- el proveedor ADO.NET necesario para la conexión; en este caso, el proveedor de SGBD es MySQL. Esto implica tener DLL y [Mysql.Data] en las referencias del proyecto.
- la cadena de conexión a la base de datos (servidor, nombre de la base de datos, propietario de la conexión y su contraseña)
- las líneas 15-29 configuran el SessionFactory de NHibernate, el objeto que sirve para obtener sesiones NHibernate. Cabe recordar que toda operación en la base de datos se realiza dentro de una sesión NHibernate. En la línea 15, se puede ver que SessionFactory está implementada por la clase Spring Spring.Data.NHibernate.LocalSessionFactoryObject, que se encuentra en DLL Spring.Data.NHibernate32.
- Línea 16: la propiedad DbProvider establece los parámetros de conexión a la base de datos (proveedor ADO.NET y cadena de conexión). En este caso, esta propiedad hace referencia al objeto DbProvider definido anteriormente en las líneas 11-13.
- Líneas 17-20: establecen la lista de ensamblados que contienen los archivos [*.hbm.xml] que configuran las entidades gestionadas por NHibernate. La línea 19 indica que estos archivos se encontrarán en el ensamblado del proyecto. Recordamos que este nombre se encuentra en las propiedades del proyecto C#. Recordamos asimismo que todos los archivos [*.hbm.xml] se han configurado para ser incorporados al ensamblado del proyecto.
- líneas 22-27: propiedades específicas de NHibernate.
- línea 24: el dialecto SQL que se utilizará será el de MySQL
- línea 25: el SQL generado por NHibernate no aparecerá en los registros de la consola. Establecer esta propiedad en true permite conocer las órdenes SQL emitidas por NHibernate. Esto puede ayudar a comprender, por ejemplo, por qué una aplicación es lenta al acceder a la base de datos.
- Línea 28: la propiedad ExposeTransactionAwareSessionFactory en true hará que Spring gestione las anotaciones de gestión de transacciones que se encuentren en el código C#. Volveremos sobre esto cuando escribamos la clase que implemente la capa [dao].
- Las líneas 32-36 definen el gestor de transacciones. Una vez más, este gestor es una clase de Spring de la clase DLL Spring.Data.NHibernate32. Este gestor necesita conocer los parámetros de conexión a la base de datos (línea 34), así como la clase SessionFactory de NHibernate (línea 35).
- Las líneas 39-43 definen las propiedades de la clase HibernateTemplate, que también es una clase de Spring. Esta clase se utilizará como clase de utilidades en la clase que implementa la capa [dao]. Facilita las interacciones con los objetos NHibernate. Esta clase tiene ciertas propiedades que hay que inicializar:
- línea 40: la propiedad SessionFactory de NHibernate
- línea 41: la propiedad TemplateFlushMode establece el modo de sincronización del contexto de persistencia NHibernate con la base de datos. El modo Auto hace que se produzca la sincronización:
- al final de una transacción
- antes de una operación select
- línea 42: las consultas HQL (Hibernate Query Language) se almacenarán en caché. Esto puede suponer una mejora en el rendimiento.
- las líneas 46-48 definen la clase de implementación de la capa [dao]
- línea 46: la capa [dao] se implementará mediante la clase [PamdaoSpringNHibernate] de DLL [pam-dao-spring-nhibernate]. Tras la instanciación de la clase, se ejecutará inmediatamente el método init de la clase. Al cerrarse el contenedor Spring, se ejecutará el método destroy de la clase.
- Línea 47: la clase [PamDaoSpringNHibernate] tendrá una propiedad HibernateTemplate que se inicializará con la propiedad HibernateTemplate de la línea 39.
2.1.5. Implementación de la capa [dao]
2.1.5.1. El esqueleto de la clase de implementación
La interfaz [IPamDao] es la siguiente:
using Pam.Dao.Entites;
namespace Pam.Dao.Service {
public interface IPamDao {
// Lista de todas las identidades de los empleados
Employe[] GetAllIdentitesEmployes();
// un empleado concreto con sus prestaciones
Employe GetEmploye(string ss);
// Lista de todas las cotizaciones
Cotisations GetCotisations();
}
}
- línea 1: se importa el espacio de nombres de las entidades de la capa [dao].
- línea 3: la capa [dao] se encuentra en el espacio de nombres [Pam.Dao.Service]. Los elementos del espacio de nombres [Pam.Dao.Entites] pueden crearse en varias instancias. Los elementos del espacio de nombres [Pam.Dao.Service] se crean en una única instancia (singleton). Esto es lo que ha justificado la elección de los nombres de los espacios de nombres.
- línea 4: la interfaz se llama [IPamDao]. Define tres métodos:
- línea 6, [GetAllIdentitesEmployes] devuelve una matriz de objetos de tipo [Employe] que representa la lista de cuidadoras infantiles en un formato simplificado (apellidos, nombre, SS).
- línea 8, [GetEmploye] devuelve un objeto [Employe]: el empleado cuyo número de la Seguridad Social se ha pasado como parámetro al método, junto con las prestaciones relacionadas con su índice.
- Línea 10: [GetCotisations] devuelve el objeto [Cotisations], que encapsula los tipos de las diferentes cotizaciones sociales que deben deducirse del salario bruto.
El esqueleto de la clase de implementación de esta interfaz con el soporte Spring / NHibernate podría ser el siguiente:
using System;
using System.Collections;
using System.Collections.Generic;
using Pam.Dao.Entites;
using Spring.Data.NHibernate.Generic.Support;
using Spring.Transaction.Interceptor;
namespace Pam.Dao.Service {
public class PamDaoSpringNHibernate : HibernateDaoSupport, IPamDao {
// campos privados
private Cotisations cotisations;
private Employe[] employes;
// inicialización
[Transaction(ReadOnly = true)]
public void init() {
...
}
// eliminación de objeto
public void destroy() {
if (HibernateTemplate.SessionFactory != null) {
HibernateTemplate.SessionFactory.Close();
}
}
// lista de todas las identidades de los empleados
public Employe[] GetAllIdentitesEmployes() {
return employes;
}
// un empleado concreto con sus prestaciones
[Transaction(ReadOnly = true)]
public Employe GetEmploye(string ss) {
....
}
// lista de cotizaciones
public Cotisations GetCotisations() {
return cotisations;
}
}
}
- línea 9: la clase [PamDaoSpringNHibernate] implementa correctamente la interfaz de la capa [dao] [IPamDao]. Además, deriva de la clase Spring [HibernateDaoSupport]. Esta clase tiene una propiedad [HibernateTemplate] que se inicializa mediante la configuración de Spring que se ha realizado (línea 2 a continuación):
<object id="pamdao" type="Pam.Dao.Service.PamDaoSpringNHibernate, pam-dao-spring-nhibernate" init-method="init" destroy-method="destroy">
<property name="HibernateTemplate" ref="HibernateTemplate"/>
</object>
- En la línea 1 anterior, se observa que la definición del objeto [pamdao] indica que los métodos init y destroy de la clase [PamDaoSpringNHibernate] deben ejecutarse en momentos concretos. Estos dos métodos están presentes en la clase, en las líneas 16 y 21.
- líneas 15 y 34: anotaciones que hacen que el método anotado se ejecute dentro de una transacción. El atributo ReadOnly=true indica que la transacción es de solo lectura. El método que se ejecuta dentro de la transacción puede lanzar una excepción. En ese caso, Spring realiza automáticamente un Rollback de la transacción. Esta anotación elimina la necesidad de gestionar una transacción dentro del método.
- Línea 16: Spring ejecuta el método init inmediatamente después de la instanciación de la clase. Veremos que su finalidad es inicializar los campos privados de las líneas 11 y 12. Se ejecutará dentro de una transacción (línea 15).
- Los métodos de la interfaz [IPamDao] se implementan en las líneas 28, 35 y 40.
- Líneas 28-30: el método [GetAllIdentitesEmployes] se limita a devolver el atributo de la línea 12 inicializado por el método init.
- Líneas 40-42: el método [GetCotisations] se limita a devolver el atributo de la línea 11 inicializado por el método init.
2.1.5.2. Métodos útiles de la clase HibernateTemplate
Utilizaremos los siguientes métodos de la clase HibernateTemplate:
ejecuta la consulta HQL y devuelve una lista de objetos de tipo T | |
ejecuta una consulta HQL parametrizada mediante «?». Los valores de estos parámetros los proporciona la tabla de objetos. | |
devuelve todas las entidades de tipo T |
Existen otros métodos útiles que no tendremos ocasión de utilizar y que permiten buscar, guardar, actualizar y eliminar entidades:
introduce en la sesión NHibernate la entidad de tipo T que tiene la clave primaria id. | |
inserta (INSERT) o actualiza (UPDATE) el objeto entité, dependiendo de si este tiene una clave primaria (UPDATE) o no (INSERT). La ausencia de clave primaria se puede configurar mediante el atributo unsaved-values del archivo de configuración de la entidad. Tras la operación SaveOrUpdate, el objeto entité se encuentra en la sesión NHibernate. | |
elimina el objeto entité de la sesión NHibernate. |
2.1.5.3. Implementación del método init
El método init de la clase [PamDaoSpringNHibernate] es, por configuración, el método que se ejecuta tras la instanciación de la clase por parte de Spring. Su objetivo es almacenar en caché local las identidades simplificadas de los empleados (nombre, apellidos, SS) y los tipos de cotización. Su código podría ser el siguiente.
[Transaction(ReadOnly = true)]
public void init() {
try {
// se obtiene la lista simplificada de empleados
IList<object[]> lignes = HibernateTemplate.Find<object[]>("select e.SS,e.Nom,e.Prenom from Employe e");
// se introduce en una tabla
employes = new Employe[lignes.Count];
int i = 0;
foreach (object[] ligne in lignes) {
employes[i] = new Employe() { SS = ligne[0].ToString(), Nom = ligne[1].ToString(), Prenom = ligne[2].ToString() };
i++;
}
// se introducen los tipos de cotización en un objeto
cotisations = (HibernateTemplate.LoadAll<Cotisations>())[0];
} catch (Exception ex) {
// se transforma la excepción
throw new PamException(string.Format("Erreur d'accès à la BD : [{0}]", ex.ToString()), 43);
}
}
- línea 5: se ejecuta una consulta HQL. Solicita los campos SS, Apellidos y Nombre de todas las entidades Employé. Devuelve una lista de objetos. Si se hubiera solicitado toda la información del empleado con la sintaxis «select e from Empleado e», se habría obtenido una lista de objetos de tipo Employe.
- líneas 7-12: esta lista de objetos se copia en una matriz de objetos de tipo Employe.
- Línea 14: se solicita la lista de todas las entidades de tipo Cotisations. Sabemos que esta lista solo tiene un elemento. Por lo tanto, recuperamos el primer elemento de la lista para obtener las tasas de cotización.
- Las líneas 7 y 14 inicializan los dos campos privados de la clase.
2.1.5.4. Implementación del método GetEmploye
El método GetEmploye debe devolver la entidad «Empleado» con un número SS determinado. Su código podría ser el siguiente:
[Transaction(ReadOnly = true)]
public Employe GetEmploye(string ss) {
IList<Employe> employés = null;
try {
// consulta
employés = HibernateTemplate.Find<Employe>("select e from Employe e where e.SS=?", new object[]{ss});
} catch (Exception ex) {
// se transforma la excepción
throw new PamException(string.Format("Erreur d'accès à la BD lors de la demande de l'employé de n° ss [{0}] : [{1}]", ss, ex.ToString()), 41);
}
// ¿Se ha recuperado algún empleado?
if (employés.Count == 0) {
// se notifica el hecho
throw new PamException(string.Format("L'employé de n° ss [{0}] n'existe pas", ss), 42);
} else {
return employés[0];
}
}
- línea 6: obtiene la lista de empleados con un número SS determinado
- línea 12: normalmente, si el empleado existe, se debe obtener una lista con un solo elemento
- línea 14: si no es así, se lanza una excepción
- línea 16: si es así, se devuelve el primer empleado de la lista
2.2. Pruebas de la capa [dao]
2.2.1. El proyecto de Visual Studio
El proyecto de Visual Studio ya se ha presentado. Recordemos que:
![]() |
- en [1], el proyecto en su totalidad
- en [2], las diferentes clases del proyecto. La carpeta [tests] contiene una prueba de consola [Main.cs] y una prueba unitaria [NUnit.cs].
- En [3], se compila el programa [Main.cs].
![]() |
- En [4], no se genera el archivo [NUnit.cs].
- El proyecto es una aplicación de consola. La clase que se ejecuta es la especificada en [5], la clase del archivo [Main.cs].
2.2.2. El programa de prueba de consola [Main.cs]
El programa de prueba [Main.cs] se ejecuta en la siguiente arquitectura:
![]() |
Se encarga de probar los métodos de la interfaz [IPamDao]. Un ejemplo básico podría ser el siguiente:
using System;
using Pam.Dao.Entites;
using Pam.Dao.Service;
using Spring.Context.Support;
namespace Pam.Dao.Tests {
public class MainPamDaoTests {
public static void Main() {
try {
// instanciación de la capa [dao]
IPamDao pamDao = (IPamDao)ContextRegistry.GetContext().GetObject("pamdao");
// lista de identidades de los empleados
foreach (Employe Employe in pamDao.GetAllIdentitesEmployes()) {
Console.WriteLine(Employe.ToString());
}
// un empleado con sus prestaciones
Console.WriteLine("------------------------------------");
Console.WriteLine(pamDao.GetEmploye("254104940426058"));
Console.WriteLine("------------------------------------");
// lista de cotizaciones
Cotisations cotisations = pamDao.GetCotisations();
Console.WriteLine(cotisations.ToString());
} catch (Exception ex) {
// visualización de excepción
Console.WriteLine(ex.ToString());
}
//pausa
Console.ReadLine();
}
}
}
- línea 11: se solicita a Spring una referencia a la capa [dao].
- líneas 13-15: prueba del método [GetAllIdentitesEmployes] de la interfaz [IPamDao]
- línea 18: prueba del método [GetEmploye] de la interfaz [IPamDao]
- línea 21: prueba del método [GetCotisations] de la interfaz [IPamDao]
Spring, NHibernate y log4net se configuran mediante el archivo [App.config] , analizado en el apartado 2.1.4.1.
La ejecución realizada con la base de datos descrita en el apartado 1.2 ofrece el siguiente resultado en la consola:
- líneas 1-2: los dos empleados de tipo [Employe] con la única información [SS, Nom, Prenom]
- línea 4: el empleado de tipo [Employe] con el número de la Seguridad Social [254104940426058]
- línea 5: los tipos de cotización
2.2.3. Pruebas unitarias con NUnit
Pasamos ahora a una prueba unitaria con NUnit. El proyecto de Visual Studio de la capa [dao] evolucionará de la siguiente manera:
![]() |
- a [1]; el programa de prueba [NUnit.cs]
- a [2,3]; el proyecto generará un archivo DLL denominado [pam-dao-spring-nhibernate.dll]
- en [4], la referencia a DLL del marco NUnit: [nunit.framework.dll]
- en [5], la clase [Main.cs] no se incluirá en DLL [pam-dao-spring-nhibernate]
- en [6], la clase [NUnit.cs] se incluirá en la clase DLL [pam-dao-spring-nhibernate]
La clase de prueba NUnit es la siguiente:
using System.Collections;
using NUnit.Framework;
using Pam.Dao.Service;
using Pam.Dao.Entites;
using Spring.Objects.Factory.Xml;
using Spring.Core.IO;
using Spring.Context.Support;
namespace Pam.Dao.Tests {
[TestFixture]
public class NunitPamDao : AssertionHelper {
// la capa [dao] que se va a probar
private IPamDao pamDao = null;
// constructor
public NunitPamDao() {
// instanciación de la capa [dao]
pamDao = (IPamDao)ContextRegistry.GetContext().GetObject("pamdao");
}
// inicialización
[SetUp]
public void Init() {
}
[Test]
public void GetAllIdentitesEmployes() {
// verificación del número de empleados
Expect(2, EqualTo(pamDao.GetAllIdentitesEmployes().Length));
}
[Test]
public void GetCotisations() {
// verificación de la tasa de cotizaciones
Cotisations cotisations = pamDao.GetCotisations();
Expect(3.49, EqualTo(cotisations.CsgRds).Within(1E-06));
Expect(6.15, EqualTo(cotisations.Csgd).Within(1E-06));
Expect(9.39, EqualTo(cotisations.Secu).Within(1E-06));
Expect(7.88, EqualTo(cotisations.Retraite).Within(1E-06));
}
[Test]
public void GetEmployeIdemnites() {
// verificación de personas
Employe employe1 = pamDao.GetEmploye("254104940426058");
Employe employe2 = pamDao.GetEmploye("260124402111742");
Expect("Jouveinal", EqualTo(employe1.Nom));
Expect(2.1, EqualTo(employe1.Indemnites.BaseHeure).Within(1E-06));
Expect("Laverti", EqualTo(employe2.Nom));
Expect(1.93, EqualTo(employe2.Indemnites.BaseHeure).Within(1E-06));
}
[Test]
public void GetEmployeIdemnites2() {
// verificación de persona inexistente
bool erreur = false;
try {
Employe employe1 = pamDao.GetEmploye("xx");
} catch {
erreur = true;
}
Expect(erreur, True);
}
}
}
- línea 11: la clase tiene el atributo [TestFixture], lo que la convierte en una clase de prueba [NUnit].
- línea 12: la clase deriva de la clase de utilidades AssertionHelper del marco NUnit (a partir de la versión 2.4.6).
- Línea 14: el campo privado [pamDao] es una instancia de la interfaz de acceso a la capa [dao]. Cabe señalar que el tipo de este campo es una interfaz y no una clase. Esto significa que la instancia [pamDao] solo da acceso a los métodos de la interfaz [IPamDao].
- Los métodos probados en la clase son aquellos que tienen el atributo [Test]. Para todos estos métodos, el proceso de prueba es el siguiente:
- en primer lugar, se ejecuta el método que tiene el atributo [SetUp]. Este sirve para preparar los recursos (conexiones de red, conexiones a bases de datos, etc.) necesarios para la prueba.
- A continuación, se ejecuta el método que se va a probar
- y, por último, se ejecuta el método con el atributo [TearDown]. Por lo general, sirve para liberar los recursos utilizados por el método con el atributo [SetUp].
- En nuestra prueba, no hay recursos que asignar antes de cada prueba y que luego haya que liberar. Por lo tanto, no necesitamos métodos con los atributos [SetUp] y [TearDown]. A modo de ejemplo, en las líneas 23-26 hemos presentado un método con el atributo [SetUp].
- Líneas 17-20: el constructor de la clase inicializa el campo privado [pamDao] utilizando Spring y [App.config].
- Líneas 29-32: prueban el método [GetAllIdentitesEmployes]
- líneas 35-42: prueban el método [GetCotisations]
- líneas 45-53: prueban el método [GetEmploye]
- líneas 56-65: prueban el método [GetEmploye] en caso de excepción.
La generación del proyecto crea los archivos DLL y [pam-dao-spring-nhibernate.dll] en la carpeta [bin/Release]:
![]() |
Cargamos el archivo DLL y [pam-dao-spring-nhibernate.dll] con la herramienta [NUnit-Gui], versión 2.5, y ejecutamos las pruebas:
![]() |
En el ejemplo anterior, las pruebas se han superado con éxito.
2.2.4. Generación de l e la DLL a partir de la capa [dao]
Una vez escrita y probada la clase [PamDaoNHibernate], se generará la clase DLL a partir de la capa [dao] de la siguiente manera:
![]() |
- [1]; los programas de prueba se excluyen del ensamblado del proyecto
- [2,3], configuración del proyecto
- [4], generación del proyecto
- el archivo DLL se genera en la carpeta [bin/Release] [5].












