visual unitarias unit test studio software pruebas patron interfaz ingenieria ejemplos aaa c# unit-testing tdd

c# - test - ¿Cómo sabes qué probar al escribir pruebas unitarias?



pruebas unitarias java (30)

Mejora nuestro código ... ¡punto!

One thing us software developers forget about when doing test driven development is the purpose behind our actions. If a unit test is being written after the production code is already in place, the value of the test goes way down (but is not completely lost).

In the true spirit for unit testing, these tests are not primarily there to "test" more of our code; or to get 90%-100% better code coverage. These are all fringe benefits of writing the tests first. The big payoff is that our production code ends be be written much better due to the natural process of TDD.

To help better communicate this idea, the following may be helpful in reading:

The Flawed Theory of Unit Tests
Purposeful Software Development

If we feel that the act of writing more unit tests is what helps us gain a higher quality product, then we may be suffering from a Cargo Cult of Test Driven Development.

Utilizando C #, necesito una clase llamada User que tenga un nombre de usuario, contraseña, bandera activa, nombre, apellido, nombre completo, etc.

Debería haber métodos para autenticar y guardar a un usuario. ¿Acabo de escribir una prueba para los métodos? ¿Y debo siquiera preocuparme por probar las propiedades, ya que son el get y setters de .Net?


Bueno, si crees que se puede romper, escribe una prueba para ello. Normalmente no pruebo setter / getter, pero permite decir que haces uno para User.Name, que concatena el nombre y el apellido, escribo una prueba para que si alguien cambia el orden para el apellido y apellido, al menos él sabría él cambió algo que fue probado.


Como entiendo las pruebas unitarias en el contexto de un desarrollo ágil, Mike, sí, debe probar los captadores y instaladores (suponiendo que sean visibles públicamente). El concepto de pruebas unitarias es probar la unidad de software, que es una clase en este caso, como una caja negra . Como los getters y setters son visibles externamente, debe probarlos junto con Authenticate and Save.


Creo que es una tontería probar getters y setters cuando solo hacen una operación simple. Personalmente no escribo pruebas complejas de unidades para cubrir cualquier patrón de uso. Intento escribir suficientes pruebas para asegurarme de que he manejado el comportamiento de ejecución normal y la cantidad de casos de error en los que puedo pensar. Escribiré más pruebas unitarias como respuesta a los informes de errores. Utilizo la prueba unitaria para asegurar que el código cumpla con los requisitos y para facilitar futuras modificaciones. Me siento mucho más dispuesto a cambiar el código cuando sé que si rompo algo, una prueba fallará.


Debe cubrir la ejecución de cada método de la clase con UT y verificar el valor de retorno del método. Esto incluye getters y setters, especialmente en el caso de que los miembros (propiedades) sean clases complejas, lo que requiere una gran asignación de memoria durante su inicialización. Llame al colocador con una cadena muy grande, por ejemplo (o algo con símbolos griegos) y verifique que el resultado sea correcto (no truncado, la codificación es buena, etc.)

En el caso de los enteros simples que también se aplican, ¿qué ocurre si pasa mucho en lugar de enteros? Esa es la razón por la que escribes UT por :)


Debería probar "cada bloque de código no trivial" usando pruebas unitarias en la medida de lo posible.

Si sus propiedades son triviales y es poco probable que alguien presente un error en ellas, entonces debería ser seguro no probarlas en una unidad.

Sus métodos Authenticate () y Save () se ven como buenos candidatos para las pruebas.


Deberías probar todo En este momento tienes getters y setters, pero un día podrías cambiarlos un poco, quizás para hacer validaciones u otras cosas. Las pruebas que escriba hoy se usarán mañana para asegurarse de que todo siga funcionando como siempre. Cuando escribe una prueba, debe olvidar consideraciones como "ahora mismo es trivial". En un contexto ágil o basado en pruebas, debe probar asumiendo futuras refactorizaciones. Además, ¿trataste de poner valores realmente extraños como cadenas extremadamente largas u otro contenido "malo"? Bueno, deberías ... nunca asumir cuán mal se puede abusar de tu código en el futuro.

En general, considero que escribir extensas pruebas de usuario es agotador por un lado. Por otro lado, a pesar de que siempre le brinda información valiosa sobre cómo debería funcionar su aplicación y le ayuda a descartar suposiciones fáciles (y falsas) (como: el nombre de usuario siempre tendrá menos de 1000 caracteres de longitud).


El código realmente trivial, como getters y setters que no tienen ningún comportamiento adicional a la configuración de un campo privado, son excesivos para probar. En 3.0 C # incluso tiene algo de azúcar sintáctico donde el compilador se ocupa del campo privado, por lo que no es necesario programarlo.

Normalmente escribo muchas pruebas muy simples para verificar el comportamiento que espero de mis clases. Incluso si es algo simple como agregar dos números. Cambio mucho entre escribir una prueba simple y escribir algunas líneas de código. La razón de esto es que luego puedo cambiar el código sin tener miedo de romper cosas en las que no pensé.


Escribiría una prueba para cualquier cosa para la que escriba código que pueda probarse fuera de la interfaz de la GUI.

Por lo general, cualquier lógica que escriba que tenga lógica de negocios la coloco dentro de otro nivel o capa de lógica de negocios.

Luego, escribir pruebas para cualquier cosa que haga algo es fácil de hacer.

Primer pase, escriba una prueba unitaria para cada método público en su "Capa lógica de negocios".

Si tuviera una clase como esta:

public class AccountService { public void DebitAccount(int accountNumber, double amount) { } public void CreditAccount(int accountNumber, double amount) { } public void CloseAccount(int accountNumber) { } }

Lo primero que haría antes de escribir cualquier código sabiendo que tenía que realizar estas acciones sería comenzar a escribir pruebas unitarias.

[TestFixture] public class AccountServiceTests { [Test] public void DebitAccountTest() { } [Test] public void CreditAccountTest() { } [Test] public void CloseAccountTest() { } }

Escribe tus pruebas para validar el código que has escrito para hacer algo. Si itera sobre una colección de cosas, y cambia algo sobre cada una de ellas, escriba una prueba que haga lo mismo y afirme que realmente sucedió.

Hay muchos otros enfoques que puede tomar, como Behavoir Driven Development (BDD), que es más complicado y no es un buen lugar para comenzar con las habilidades de prueba de su unidad.

Entonces, la moraleja de la historia es probar cualquier cosa que haga algo que pueda preocuparle, mantener las pruebas de la unidad probando cosas específicas que son de pequeño tamaño, muchas pruebas son buenas.

Mantenga su lógica de negocio fuera de la capa de interfaz de usuario para que pueda escribir fácilmente pruebas para ellos, y estará bien.

Recomiendo TestDriven.Net o ReSharper ya que ambos se integran fácilmente en Visual Studio.


Esta pregunta parece ser una cuestión de dónde se traza una línea sobre qué métodos se prueban y cuáles no.

Los establecedores y captadores para la asignación de valor se han creado teniendo en cuenta la consistencia y el crecimiento futuro, y previendo que, en el futuro, el organismo incumplidor puede convertirse en operaciones más complejas. Tendría sentido poner en práctica pruebas unitarias de esos métodos, también en aras de la coherencia y el crecimiento futuro.

El objetivo principal es la fiabilidad del código, especialmente durante el cambio para agregar funcionalidad adicional. No conozco a nadie que haya sido despedido por incluir setters / getters en la metodología de prueba, pero estoy seguro de que existen personas que deseaban haber probado métodos de los que solo sabían o pueden recordar que eran simples set / get wrappers pero que no era más largo el caso.

Tal vez otro miembro del equipo amplió los métodos set / get para incluir la lógica que ahora necesita ser probada pero luego no creó las pruebas. Pero ahora su código llama a estos métodos y no está consciente de que cambiaron y necesitan pruebas en profundidad, y las pruebas que realiza en desarrollo y control de calidad no desencadenan el defecto, pero los datos comerciales reales en el primer día de lanzamiento desencadenarlo

Los dos compañeros de equipo ahora debatirán sobre quién dejó caer el balón y no pudieron realizar pruebas unitarias cuando el conjunto / se transforma para incluir una lógica que puede fallar pero que no está cubierta por una prueba unitaria. Al compañero de equipo que originalmente escribió el set / get le será más fácil salir limpio si las pruebas se implementaron desde el primer día en el set / get simple.

Mi opinión es que unos minutos de tiempo "desperdiciado" que cubra TODOS los métodos con pruebas unitarias, incluso triviales, podrían ahorrar días de dolor de cabeza en el futuro y la pérdida de dinero / reputación del negocio y la pérdida del trabajo de alguien.

Y el hecho de que haya envuelto métodos triviales con pruebas unitarias puede ser visto por ese compañero de equipo junior cuando cambian los métodos triviales en no triviales y les piden que actualicen la prueba, y ahora nadie tiene problemas porque el defecto estaba contenido de alcanzar la producción.

La forma en que codificamos y la disciplina que se puede ver en nuestro código pueden ayudar a otros.


Idealmente, habría hecho sus pruebas de unidad mientras escribía la clase. Así es como debe hacerlo cuando usa Test Driven Development. Agregue las pruebas a medida que implementa cada punto de función, asegurándose de cubrir también las cajas de borde con la prueba.

Escribir las pruebas después es mucho más doloroso, pero factible.

Esto es lo que haría en su posición:

  1. Escribe un conjunto básico de pruebas que prueben la función central.
  2. Obtenga NCover y ejecútelo en sus pruebas. La cobertura de su prueba probablemente será de alrededor del 50% en este momento.
  3. Siga agregando pruebas que cubran sus casos extremos hasta que obtenga una cobertura de alrededor del 80% -90%

Esto debería proporcionarle un buen conjunto de pruebas de funcionamiento que actuarán como un buen amortiguador contra las regresiones.

El único problema con este enfoque es que el código debe diseñarse para que se pueda probar de esta manera. Si cometió algún error de acoplamiento desde el principio, no podrá obtener una cobertura alta muy fácilmente.

Es por eso que es realmente importante escribir las pruebas antes de escribir el código. Te obliga a escribir código que está débilmente acoplado.


Incluso get / set puede tener consecuencias extrañas, dependiendo de cómo se hayan implementado, por lo que deben tratarse como métodos.

Cada prueba de estos deberá especificar conjuntos de parámetros para las propiedades, definiendo propiedades aceptables e inaceptables para asegurar que las llamadas regresen / fallan de la manera esperada.

También debe conocer los errores de seguridad, como un ejemplo de inyección de SQL, y probarlos.

Entonces sí, debes preocuparte por probar las propiedades.


La regla es que tienes que probar cada pieza de lógica que escribes. Si implementó alguna funcionalidad específica en getters y setters, creo que vale la pena probarlos. Si solo asignan valores a algunos campos privados, no se moleste.


La respuesta canónica es "probar cualquier cosa que pueda romperse". Si está seguro de que las propiedades no se romperán, no las pruebe.

Y una vez que se descubre que algo se ha roto (encuentras un error), obviamente significa que debes probarlo. Escribe una prueba para reproducir el error, mira si falla, luego arregla el error, luego mira el pase de prueba.


Muchas respuestas excelentes a esto también están en mi pregunta: "¿ Comienzo TDD - Desafíos? ¿Soluciones? ¿Recomendaciones? "

También puedo recomendar que eche un vistazo a mi publicación en el blog (que fue inspirada en parte por mi pregunta). Tengo buenos comentarios al respecto. A saber:

No sé por dónde empezar?

  • Comenzar de nuevo. Solo piense en escribir pruebas cuando está escribiendo un nuevo código. Esto puede volver a trabajar con el código anterior o con una función completamente nueva.
  • Comience simple. No salgas corriendo y tratando de darte una vuelta por un marco de prueba además de ser TDD-esque. Debug.Assert funciona bien. Úselo como punto de partida. No se mezcla con tu proyecto ni crea dependencias.
  • Comience positivo. Está tratando de mejorar su oficio, se siente bien al respecto. He visto muchos desarrolladores que están contentos de estancarse y no probar cosas nuevas para mejorarse. Estás haciendo lo correcto, recuerda esto y te ayudará a evitar que te rindas.
  • Comience listo para un desafío. Es bastante difícil comenzar a hacer las pruebas. Espere un desafío, pero recuerde: los desafíos se pueden superar.

Solo prueba lo que esperas

Tuve problemas reales la primera vez que comencé porque constantemente me sentaba allí tratando de descubrir cada posible problema que pudiera ocurrir y luego intentaba probarlo y solucionarlo. Esta es una forma rápida de un dolor de cabeza. Las pruebas deben ser un verdadero proceso YAGNI. Si sabes que hay un problema, escribe una prueba para ello. De lo contrario, no te molestes.

Solo prueba una cosa

Cada caso de prueba solo debería probar una sola cosa. Si alguna vez te encuentras poniendo "y" en el nombre del caso de prueba, estás haciendo algo mal.

Espero que esto signifique que podemos pasar de "getters and setters" :)


No está de más escribir pruebas unitarias para tus getters y setters. En este momento, es posible que solo estén haciendo get / sets de campo bajo el capó, pero en el futuro puede tener lógica de validación o dependencias entre propiedades que deben ser probadas. Es más fácil escribirlo ahora mientras lo piensas y luego recordar actualizarlo si es que llega ese momento.


No probaría la configuración real de las propiedades. Me preocuparía más cómo esas propiedades se llenen por el consumidor y con qué las llenan. Con cualquier prueba, debe sopesar los riesgos con el tiempo / costo de las pruebas.


No pruebe el código obviamente operativo (repetitivo). Entonces, si tus setters y getters son solo "propertyvalue = value" y "return propertyvalue" no tiene sentido probarlos.


Otra respuesta canónica Esto, creo, de Ron Jeffries:

Solo prueba el código que deseas trabajar.


Para los módulos simples que pueden terminar en un kit de herramientas, o en un tipo de proyecto de código abierto, debe probar tanto como sea posible, incluidos los captadores y los que realizan ajustes triviales. Lo que desea tener en cuenta es que generar un test de unidad mientras escribe un módulo en particular es bastante simple y directo. Agregar getters y setters es un código mínimo y se puede manejar sin pensarlo mucho. Sin embargo, una vez que su código se coloca en un sistema más grande, este esfuerzo adicional puede protegerlo contra los cambios en el sistema subyacente, como los cambios de tipo en una clase base. Probar todo es la mejor forma de tener una regresión completa.


Personalmente, "probaría cualquier cosa que pueda romperse" y el getter simple (o incluso mejores propiedades de auto) no se romperá. Nunca he tenido una declaración de devolución simple y, por lo tanto, nunca he tenido una prueba para ellos. Si los buscadores tienen un cálculo dentro de ellos o alguna otra forma de declaraciones, ciertamente agregaría pruebas para ellos.

Personalmente utilizo Moq como un marco de objeto falso y luego verifico que mi objeto llama a los objetos circundantes de la manera que debería.


Pon a prueba tu código, no el idioma.

Una prueba unitaria como:

Integer i = new Integer(7); assert (i.instanceOf(integer));

solo es útil si está escribiendo un compilador y existe la posibilidad de que su instanceof método no funcione.

No pruebe cosas que pueda confiar en el idioma para hacer cumplir. En su caso, me centraría en sus métodos de autenticación y guardado, y escribiría pruebas que garantizaran que pudieran manejar valores nulos en cualquiera o todos esos campos correctamente.


Probar el código repetitivo es una pérdida de tiempo, pero como dice Slavo, si agrega un efecto secundario a sus getters / setters, entonces debe escribir una prueba para acompañar esa funcionalidad.

Si está realizando un desarrollo basado en pruebas, primero debe escribir el contrato (por ejemplo, la interfaz) y luego escribir las pruebas para ejercitar esa interfaz que documenta el resultado / comportamiento esperado. Luego, escriba sus métodos ellos mismos, sin tocar el código en las pruebas de su unidad. Finalmente, tome una herramienta de cobertura de código y asegúrese de que sus pruebas ejerzan todas las rutas lógicas en su código.


Recomendaría escribir múltiples pruebas para sus métodos Autenticar y Guardar. Además del caso de éxito (donde se proporcionan todos los parámetros, todo está escrito correctamente, etc.), es bueno tener pruebas para varios casos de falla (parámetros incorrectos o faltantes, conexiones de bases de datos no disponibles, si corresponde, etc.). Recomiendo Pragmatic Unit Testing en C # con NUnit como referencia.

Como han dicho otros, las pruebas unitarias para getters y setters son exageradas, a menos que haya una lógica condicional en sus getters y setters.


Si bien es posible adivinar correctamente dónde necesita probar su código, generalmente creo que necesita métricas para respaldar esta suposición. Las pruebas de unidad en mi opinión van de la mano con las métricas de cobertura de código.

Código con muchas pruebas, pero una cobertura pequeña no se ha probado bien. Dicho esto, el código con una cobertura del 100%, pero no prueba el límite y los casos de error tampoco es bueno.

Desea un equilibrio entre alta cobertura (90% mínimo) y datos variables de entrada.

Recuerde probar para "basura adentro"!

Además, una prueba unitaria no es una prueba unitaria a menos que verifique una falla. Las pruebas unitarias que no tienen afirmaciones o están marcadas con excepciones conocidas simplemente probarán que el código no muere cuando se ejecuta.

¡Debe diseñar sus pruebas para que siempre informen sobre fallas o datos inesperados / no deseados!


Si los métodos Autenticar y Guardar usan las propiedades, sus pruebas tocarán indirectamente las propiedades. Siempre que las propiedades solo brinden acceso a los datos, entonces las pruebas explícitas no deberían ser necesarias (a menos que obtenga una cobertura del 100%).


Si realmente son triviales, entonces no te molestes en probar. Por ejemplo, si se implementan de esta manera;

public class User { public string Username { get; set; } public string Password { get; set; } }

Si, por otro lado, está haciendo algo inteligente (como encriptar y descifrar la contraseña en getter / setter), entonces pruébela.


Yo probaría tus getters y setters. Dependiendo de quién escriba el código, algunas personas cambian el significado de los métodos getter / setter. He visto la inicialización de variables y otra validación como parte de los métodos getter. Para probar este tipo de cosas, desearía que las pruebas unitarias cubrieran ese código explícitamente.


en general, cuando un método solo se define para ciertos valores, pruebe los valores en y sobre el borde de lo que es aceptable. En otras palabras, asegúrese de que su método haga lo que se supone que debe hacer, pero nada más . Esto es importante, porque cuando vas a fallar, quieres fallar temprano.

En las jerarquías de herencia, asegúrese de probar el cumplimiento de LSP .

Probar getters y setters predeterminados no me parece muy útil, a menos que planees hacer una validación más adelante.


Esto me llevó a pruebas unitarias y me hizo muy feliz

Acabamos de comenzar a hacer pruebas unitarias. Durante mucho tiempo supe que sería bueno comenzar a hacerlo, pero no tenía idea de cómo empezar y, lo que es más importante, qué probar.

Luego tuvimos que reescribir una pieza importante de código en nuestro programa de contabilidad. Esta parte fue muy compleja ya que involucraba muchos escenarios diferentes. La parte de la que estoy hablando es un método para pagar ventas y / o comprar facturas ya ingresadas en el sistema contable.

Simplemente no sabía cómo comenzar a codificarlo, ya que había tantas opciones de pago diferentes. Una factura podría ser de $ 100 pero el cliente solo transfirió $ 99. Tal vez ha enviado facturas de ventas a un cliente pero también ha comprado a ese cliente. Entonces lo vendiste por $ 300 pero lo compraste por $ 100. Puede esperar que su cliente le pague $ 200 para saldar el saldo. ¿Y qué pasa si se vende por $ 500 pero el cliente le paga solo $ 250?

Por lo tanto, tenía un problema muy complejo para resolver con muchas posibilidades de que un escenario funcionara perfectamente pero que fuera incorrecto en otro tipo de combinación de factura / pago.

Aquí es donde las pruebas unitarias llegaron al rescate.

Empecé a escribir (dentro del código de prueba) un método para crear una lista de facturas, tanto para ventas como para compras. Luego escribí un segundo método para crear el pago real. Normalmente, un usuario ingresa esa información a través de una interfaz de usuario.

Luego creé el primer TestMethod, probando un pago muy simple de una sola factura sin descuentos de pago. Toda la acción en el sistema ocurriría cuando un pago bancario se guardara en la base de datos. Como puede ver, creé una factura, creé un pago (una transacción bancaria) y guardé la transacción en el disco. En mis afirmaciones pongo los números correctos que terminan en la transacción del Banco y en la Factura vinculada. Compruebo el número de pagos, los montos de pago, el monto del descuento y el saldo de la factura después de la transacción.

Después de que la prueba se ejecutara iría a la base de datos y verificaría si lo que esperaba estaba allí.

Después de escribir la prueba, comencé a codificar el método de pago (parte de la clase BankHeader). En la codificación solo me molesté con el código para hacer el primer pase de prueba. Todavía no pensaba en los otros escenarios más complejos.

Ejecuté la primera prueba, solucioné un pequeño error hasta que pasara mi prueba.

Luego comencé a escribir la segunda prueba, esta vez trabajando con un descuento de pago. Después de escribir la prueba, modifiqué el método de pago para admitir descuentos.

Mientras probaba la corrección con un descuento de pago, también probé el pago simple. Ambas pruebas deberían pasar, por supuesto.

Luego trabajé para llegar a los escenarios más complejos.

1) Piense en un nuevo escenario

2) Escribe una prueba para ese escenario

3) Ejecute esa prueba única para ver si pasaría

4) De lo contrario, depuraré y modificaré el código hasta que pase.

5) Al modificar el código continué ejecutando todas las pruebas

Así es como logré crear mi método de pago muy complejo. Sin pruebas unitarias, no sabía cómo comenzar a codificar, el problema parecía abrumador. Con las pruebas podría comenzar con un método simple y extenderlo paso a paso con la seguridad de que los escenarios más simples seguirían funcionando.

Estoy seguro de que el uso de pruebas unitarias me ahorró unos días (o semanas) de codificación y estoy más o menos garantizando la corrección de mi método.

Si luego pienso en un nuevo escenario, puedo agregarlo a las pruebas para ver si funciona o no. Si no, puedo modificar el código pero aún así estar seguro de que los otros escenarios siguen funcionando correctamente. Esto ahorrará días y días en la fase de mantenimiento y reparación de errores.

Sí, incluso el código probado aún puede tener errores si un usuario hace cosas que no pensaste o le impidió hacer

A continuación, se incluyen algunas de las pruebas que creé para probar mi método de pago.

public class TestPayments { InvoiceDiaryHeader invoiceHeader = null; InvoiceDiaryDetail invoiceDetail = null; BankCashDiaryHeader bankHeader = null; BankCashDiaryDetail bankDetail = null; public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date) { ...... ...... } public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount) { ...... ...... ...... } [TestMethod] public void TestSingleSalesPaymentNoDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 1, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] public void TestSingleSalesPaymentDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); } [TestMethod] [ExpectedException(typeof(ApplicationException))] public void TestDuplicateInvoiceNumber() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("100", true, 2, "01-09-2008")); list.Add(CreateSales("200", true, 2, "01-09-2008")); bankHeader = CreateMultiplePayments(list, 3, 300, 0); bankHeader.Save(); Assert.Fail("expected an ApplicationException"); } [TestMethod] public void TestMultipleSalesPaymentWithPaymentDiscount() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("119", true, 11, "01-09-2008")); list.Add(CreateSales("400", true, 12, "02-09-2008")); list.Add(CreateSales("600", true, 13, "03-09-2008")); list.Add(CreateSales("25,40", true, 14, "04-09-2008")); bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount); Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount); Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance); } [TestMethod] public void TestSettlement() { IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>(); list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase bankHeader = CreateMultiplePayments(list, 22, 200, 0); bankHeader.Save(); Assert.AreEqual(1, bankHeader.BankCashDetails.Count); Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count); Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount); Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance); Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance); }