Pruebas Unitarias y Principio de Inversión de Dependencias en .NET
Clase 15 de 16 • Curso de Principios SOLID en C# y .NET
Contenido del curso
Clase 15 de 16 • Curso de Principios SOLID en C# y .NET
Contenido del curso
Miguel Santiago Gómez Suárez
Carlos Andres Bohorquez Duran
Carlos Isael Ramírez González
Carlos Gomez
Carlos Fernando Galeano Espinosa
Joel Angel David Barrantes Palacios
Juan Navas
Hermann Klaus Seer Diaz
JULIAN ANDRES ALZATE HURTADO
Marcel Solera
José David Gómez Brenes
Thomas Isaid Castro Navarro
César Augusto Poveda Floréz
César Augusto Poveda Floréz
Stanley Melgar
César Augusto Poveda Floréz
Jason Galvis Camargo
César Augusto Poveda Floréz
Joseling Jomara González Contreras
Joseph Ruiz
Jose Noriega
ROMMEL DUAREZ SAENZ
Sebastian Londoño
Aldhair Vera Camacho
Sebastian Jaramillo
Franklin Alexander Reyes Andres
Hola, me parece que la explicación fue muy bien lograda con relación al principio en sí. Sin embargo, si es necesario una capacitación previa sobre la inyección de dependencia, cuáles son sus usos, conceptos básicos y demás, que permitan ir un poco más firme siguiendo el paso a paso del contexto del principio dentro del código.
Este principio requiere un curso de inyeccion de dependencias antes, me perdi completamente, pero es mi culpa.
Si, de todos lo sprincipios SOLID creo que el de Dependecy inversion es el mas complejo.
Mi aporte para la creación de la prueba unitaria Add:
Modifique el método Add en el StudentController:
La razón por la que modifique este método es porque en las pruebas unitarias no me recibía void, debía retornar algo.
[HttpPost] public Student Add([FromBody] Student student) { studentRepository.Add(student); logbook.Add($"The Student {student.Fullname} have been added"); return student; }
Cree el método Add en la prueba unitaria de la siguiente manera:
[Fact] public void Add() { var LogbookMock = new Mock<ILogbook>(); var stundentRepositoryMock = new Mock<IStudentRepository>(); var studentController = new StudentController(stundentRepositoryMock.Object, LogbookMock.Object); var student = new Student(1, "Carlos Pérez", new List<double>() { 4, 6.5 }); var resultAddStudents = studentController.Add(student); Assert.NotNull(resultAddStudents); }
Muchas Gracias!
Desde mi perspectiva, considero que el test no está realizado de forma adecuada. Es cierto que el test pasa, pero eso no garantiza que se esté probando correctamente el método "Add". Deberíamos validar si el valor agregado está presente, o incluso podríamos verificar la cantidad de valores en el IEnumerable que se obtiene mediante "studentController.Get()".
Además, es importante tener en cuenta que "studentController.Add(student)" no devuelve ningún valor, por lo tanto no es necesario crear una variable como se muestra en el código: "var resultAddStudents = studentController.Add(student)".
Espero que ayude mi comentario
Esta debería ser la parte II, la clase 15/16.
Excelente clase! Muy buen ejemplo y muy bien explicado
Les recomiendo al full, el Curso de Unit Testing con C# y .NET, es super completo lo dicta el mismo profesor y les puede ser muy útil al momento de llegar hasta este punto del test.
Tuve que verlo 3 veces para poder entender.
El mejor curso sobre SOLID que he visto en mi vida, muchas gracias Profe.
Este video es: Aplicando el principio de inversión de la dependencia - Parte II
No me quedo muy claro el tema de las pruebas y la inyección de dependencia en el tema de las pruebas. Si alguien pudiera ayudarme a entender. Cual es el fin de las pruebas, si no estoy probando mis clases que a la final usare en mi API?, si yo hago inyección de dependencias lo que hago en las pruebas es usar otras clases que no son las que tienen mi lógica real que va usar la API. Lo entiendo muy bien de porque aplicarlo en las API porque esto permite, fácilmente tener varias implementaciones, pero en las pruebas, lo que entiendo es que podria probar diferentes implementaciones de la misma clase o algo asi?
Ya entendi XD
Hace falta un curso de unit testing con dotnet. Eso del Mock me generó curiosidad.
Si de acuerdo.
El profesor es muy buen maestro, sin embargo me quede crudo en esta clase, hay cosas que se requieren saber para poder llegar a este punto. creo que me falta mucho para entender esto.
Si de acuerdo, con el tema de las API y lo de las pruebas unitarias hay varias cositas que se mencionan ahi que ni idea. Pero bueno, a investigar por nuestra cuenta. Saludos.
I share the test Add method
Mi unit test usando xUnit framework y la librería Moq:
[Fact] public void AddStudent() { // Given var LogbookMock = new Mock<ILogbook>(); var studentRepositoryMock = new Mock<IStudentRepository>(); var studentController = new StudentController(studentRepositoryMock.Object, LogbookMock.Object); var student = new Student() { Id = 4, Fullname = "Bart Simpson", Grades = new List<double>() { 3, 4.5 } }; // When studentController.Add(student); // Then studentRepositoryMock.Verify(p => p.Add(It.IsAny<Student>()), Times.Once); LogbookMock.Verify(p => p.Add(It.IsAny<string>()), Times.Once); } ```Validando que el controlador interactúa correctamente con sus dependencias. Nota: no es necesario que el método Add del Controlador retorne un valor.
Reto - Añadir pruebas para método add
Mi estrategia fue verificar que lo que pretendemos que pase dentro de la acción Add esté pasando realmente, ya que esta no devuelve ningún resultado.
## Código
[Fact] public void AddStudent() { var logbookMock = new Mock<ILogbook>(); var studentRepositoryMock = new Mock<IStudentRepository>(); var studentController = new StudentController(studentRepositoryMock.Object, logbookMock.Object); var student = new Student() { Id = 1, FullName = "John Doe", Grades = [10, 7] }; studentController.Add(student); studentRepositoryMock.Verify(repo => repo.Add(It.IsAny<Student>()), Times.Once); logbookMock.Verify(logbook => logbook.Add($"The Student {student.FullName} has been added"), Times.Once); }
en conclusión en vez de crear objetos dentro, desde afuera de la clase debes inyectar objetos abstractos
Excelente curso de SOLID, para el principio de inversión de la dependencia sería bueno tener mas ejemplos practicos ya que es el principio mas complejo.
Hola, dejo mi solución al problema y añado los diferentes scripts que modifiqué.using Microsoft.AspNetCore.Mvc;namespace DependencyInversion;using Xunit;using DependencyInversion.Controllers;using Moq;using DependencyInversion; namespace Api.Tests;
public class StudentTest { // [Fact] // public void GetStudent() // { // var studentController = new StudentController(); // var resultGetStudents = studentController.Get(); // Assert.NotNull(resultGetStudents); // Assert.Equal(3, resultGetStudents.Count()); // }
[Fact] public void GetStudent() { var LogbookMock = new Mock<ILogbook>(); var stundentRepositoryMock = new Mock<IStudentRepository>(); stundentRepositoryMock.Setup(p=> p.GetAll()) .Returns(new List<Student>() { new Student(1, "Pepito Pérez", new List<double>() { 3, 4.5 }), new Student(2, "Mariana Lopera", new List<double>() { 4, 5 }), new Student(3, "José Molina", new List<double>() { 2, 3 }) }); var studentController = new StudentController(stundentRepositoryMock.Object, LogbookMock.Object); var resultGetStudents = studentController.Get(); Assert.NotNull(resultGetStudents); Assert.Equal(3, resultGetStudents.Count()); } [Fact] public void AddStudent() { var LogbookMock = new Mock<ILogbook>(); var studentRepositoryMock = new Mock<IStudentRepository>(); studentRepositoryMock.Setup(p=> p.GetAll()) .Returns(new List<Student>() { new Student(1, "Pepito Pérez", new List<double>() { 3, 4.5 }), new Student(2, "Mariana Lopera", new List<double>() { 4, 5 }), new Student(3, "José Molina", new List<double>() { 2, 3 }), new Student(4, "Aldhair Vera", new List<double>() { 5,5 }) }); var studentController = new StudentController(studentRepositoryMock.Object, LogbookMock.Object); studentController.Add(new Student(4, "Aldhair Vera", new List<double>() { 5,5 })); var resultGetStudents = studentController.Get(); Assert.NotNull(resultGetStudents); Assert.Equal(4, resultGetStudents.Count()); }} public class Student{ public int Id { get; set; } public string Fullname { get; set; } public List<double> Grades { get; set; } public Student() { this.Fullname = string.Empty; this.Grades = new List<double>(); } public Student(int id, string fullname, List<double> grades) { this.Id = id; this.Fullname = fullname; this.Grades = grades; } public string ToString() { string content = $"Student: {this.Id} - {this.Fullname} - Grades: "; for (int i = 0; i < this.Grades.Count; i++) { content += $" {this.Grades[i]}{((i >= this.Grades.Count - 1) ? "" : " - ")}"; } return content; }}
namespace DependencyInversion.Controllers; [ApiController, Route("student")]public class StudentController : ControllerBase{ IStudentRepository studentRepository; ILogbook logbook; public StudentController(IStudentRepository student, ILogbook log){ studentRepository = student; logbook = log; } [HttpGet] public IEnumerable<Student> Get() { logbook.Add($"returning student's list"); return studentRepository.GetAll(); } [HttpPost] public void Add([FromBody]Student student) { studentRepository.Add(student); logbook.Add($"The Student {student.Fullname} have been added"); Console.WriteLine($"The Student {student.ToString()} have been added"); foreach(var st in studentRepository.GetAll()){ Console.WriteLine($"{st.ToString()}"); } }}
using Microsoft.AspNetCore.Mvc; namespace DependencyInversion.Controllers; [ApiController, Route("student")] public class StudentController : ControllerBase { IStudentRepository studentRepository; ILogbook logbook; public StudentController(IStudentRepository student, ILogbook log){ studentRepository = student; logbook = log; } [HttpGet] public IEnumerable<Student> Get() { logbook.Add($"returning student's list"); return studentRepository.GetAll(); } [HttpPost] public void Add([FromBody]Student student) { studentRepository.Add(student); logbook.Add($"The Student {student.Fullname} have been added"); Console.WriteLine($"The Student {student.ToString()} have been added"); foreach(var st in studentRepository.GetAll()){ Console.WriteLine($"{st.ToString()}"); } } } ``````js namespace DependencyInversion; public class Student { public int Id { get; set; } public string Fullname { get; set; } public List<double> Grades { get; set; } public Student() { this.Fullname = string.Empty; this.Grades = new List<double>(); } public Student(int id, string fullname, List<double> grades) { this.Id = id; this.Fullname = fullname; this.Grades = grades; } public string ToString() { string content = $"Student: {this.Id} - {this.Fullname} - Grades: "; for (int i = 0; i < this.Grades.Count; i++) { content += $" {this.Grades[i]}{((i >= this.Grades.Count - 1) ? "" : " - ")}"; } return content; } } ``````js using Xunit; using DependencyInversion.Controllers; using Moq; using DependencyInversion; namespace Api.Tests; public class StudentTest { // [Fact] // public void GetStudent() // { // var studentController = new StudentController(); // var resultGetStudents = studentController.Get(); // Assert.NotNull(resultGetStudents); // Assert.Equal(3, resultGetStudents.Count()); // } [Fact] public void GetStudent() { var LogbookMock = new Mock<ILogbook>(); var stundentRepositoryMock = new Mock<IStudentRepository>(); stundentRepositoryMock.Setup(p=> p.GetAll()) .Returns(new List<Student>() { new Student(1, "Pepito Pérez", new List<double>() { 3, 4.5 }), new Student(2, "Mariana Lopera", new List<double>() { 4, 5 }), new Student(3, "José Molina", new List<double>() { 2, 3 }) }); var studentController = new StudentController(stundentRepositoryMock.Object, LogbookMock.Object); var resultGetStudents = studentController.Get(); Assert.NotNull(resultGetStudents); Assert.Equal(3, resultGetStudents.Count()); } [Fact] public void AddStudent() { var LogbookMock = new Mock<ILogbook>(); var studentRepositoryMock = new Mock<IStudentRepository>(); studentRepositoryMock.Setup(p=> p.GetAll()) .Returns(new List<Student>() { new Student(1, "Pepito Pérez", new List<double>() { 3, 4.5 }), new Student(2, "Mariana Lopera", new List<double>() { 4, 5 }), new Student(3, "José Molina", new List<double>() { 2, 3 }), new Student(4, "Aldhair Vera", new List<double>() { 5,5 }) }); var studentController = new StudentController(studentRepositoryMock.Object, LogbookMock.Object); studentController.Add(new Student(4, "Aldhair Vera", new List<double>() { 5,5 })); var resultGetStudents = studentController.Get(); Assert.NotNull(resultGetStudents); Assert.Equal(4, resultGetStudents.Count()); } }
Sería ideal entender APIs y Tests antes de realizar este curso, sino se hace sumamente confuso lo explicado.
que buena forma de explicarla en ambas partes muy complejo el principio pero explicación entendible totalmente