Ya tengo una función C# escrita (fue escrita hace años), me han pedido que cubra este método con pruebas unitarias.
public string PlaceOrder(int requestId, string orderedby) { try { using (DatabaseContext dbContext = new DatabaseContext("myConnectionStringHere")) { var req = dbContext.Orders.Where(row => row.id == requestId).FirstOrDefault(); if (req == null) return "not found"; req.status="A"; dbContext.SaveChanges(); return "found"; } } catch (Exception ex) { return "error"; } } Ahora, durante la prueba de la unidad, necesito asegurarme de que no escriba nada en la base de datos, por lo que tengo que MOQ . ¿Cómo puedo hacer MOQ ? Contiene el bloque de Using .
Sé que la arquitectura podría haber sido mejor y que se deberían haber seguido los patrones de diseño, pero no puedo cambiar la estructura de la aplicación, ya que es una aplicación heredada.
Hay que cambiar muchas cosas aquí:
1:
No implemente su cadena de conexión de esta manera, directamente en la base del código. En su lugar, inserte su base de datos en sus clases.
entonces este pseudocódigo debería ayudar con la idea general.
public void ConfigureService(IServiceCollection serviceCollection) { ... string connectionString = //secure storage; serviceCollection.AddDbContext<DatabaseContext>(options => { options.UseSqlServer(connectionString); }); ... }Y luego
public class OrderRepository { private IServiceScopeFactory _serviceScopeFactory ; public OrderRepository(IServiceScopeFactory serviceScopeFactory ){ _serviceScopeFactory = serviceScopeFactory ; } ... public string PlaceOrder(int requestId, string orderedby) { try { using (var context = serviceScopeFactory.CreateScope()) { var req = context.Orders.Where(row => row.id == requestId).FirstOrDefault(); if (req == null) return "not found"; req.status="A"; context.SaveChanges(); return "found"; } } catch (Exception ex) { return "error"; } } ... }si desea realizar una prueba de integración, puede usar una base de datos InMemory para emular lo que desee. O puede conectarse a una base de datos "real" y hacerlo de esa manera.
Si desea convertirlo en una prueba de unidad, puede ver en este enlace: Cómo configurar un simulacro de DbContext
2:
devolver una cadena que dice encontrado/no encontrado para un pedido que se está realizando parece extremadamente contraproducente.
si su objetivo es registrar esta información, proporcione un registrador DI, que pueda registrar esto. (Intente importar la interfaz ILogger, es una extensión de Microsoft en el registro, no recuerdo el nombre del paquete nuget) debería permitirle iniciar sesión con DI de manera muy eficiente.
Si su objetivo es permitir que una posible interfaz de usuario muestre este mensaje, no hay forma de que el contenido del mensaje se origine en la lógica del back-end o del dominio.
Al menos no así.
Luego, debe crear una interfaz para una respuesta y devolver una implementación de dicha interfaz, que existe en otro lugar como mínimo, pero incluso eso es un poco como orinarse en los pantalones. (Y contiene un mensaje compatible con la interfaz de usuario, puede contener un posible seguimiento/excepción de pila) y otra posible información relevante, como qué identificación estaba tratando de realizar un pedido, etc.)
Debe convertirlo en algo que suceda en la interfaz entre su interfaz de usuario y la lógica del dominio, siempre que sea para lo que está destinada la cadena. Donde esperaría ver el manejo de errores.
3: ¿WTF está arriba con la trampa? solo devuelves error? Bien ? ¿Qué error? ¿Pierdes el seguimiento de la pila de esta manera? Alguien debería ser castigado por eso.