with verifiable unit tests setup objetos mock and c# unit-testing moq

c# - verifiable - verify moq



Usando Moq para anular métodos virtuales en la misma clase (3)

Probablemente pueda usar burlas parciales en este escenario, aunque todos sus métodos deberían ser virtuales:

var mock = new Moq.Mock<RenewalService>(); mock.Setup(m => m.GetNextRenewalDate(It.IsAny<Guid>())).Returns(null); mock.CallBase = true; var results = mock.Object.IsLastRenewalOfYear(...);

Estamos utilizando Moq para probar nuestras clases de servicio, pero estamos atascados en cómo probar situaciones en las que un método de servicio llama a otro método de servicio de la misma clase. Intenté configurar el método que se llama a virtual, pero todavía no podía averiguar qué hacer en Moq. Por ejemplo:

public class RenewalService : IRenewalService { //we''ve already tested this public virtual DateTime? GetNextRenewalDate(Guid clientId) { DateTime? nextRenewalDate = null; //...<snip> a ton of already tested stuff... return nextRenewalDate; } //but want to test this without needing to mock all //the methods called in the GetNextRenewalDate method public bool IsLastRenewalOfYear(Renewal renewal) { DateTime? nextRenewalDate = GetNextRenewalDate(renewal.Client.Id); if (nextRenewalDate == null) throw new Exceptions.DataIntegrityException("No scheduled renewal date, cannot determine if last renewal of year"); if (nextRenewalDate.Value.Year != renewal.RenewDate.Year) return true; return false; } }

En el ejemplo anterior, nuestro método GetNextRenewalDate es bastante complicado, y ya lo hemos probado por unidad. Sin embargo, queremos probar el IsLastRenewalOfYear más simple sin necesidad de burlarnos de todo lo necesario para GetNextRenewalDate. Básicamente, solo queremos burlarnos de GetNextRenewalDate.

Me doy cuenta de que podría crear una nueva clase que anule GetNextRenewalDate y probar la nueva clase, pero ¿hay alguna forma en que pueda aprovechar Moq para hacer esto más simple?


Edit : Estoy de acuerdo en que esta no es la respuesta correcta para el caso de Andrew. Quiero dejar esta respuesta aquí para el hilo de comentarios. Por favor, no voten más abajo :)

Antes de editar:

En general, los marcos de objetos simulados no están diseñados para simplificar el escenario de una sola clase, están diseñados para aislar su código para que pueda probar una sola clase.

Si intenta usar un marco de objeto simulado para resolver esto, el marco simplemente creará una clase derivada y sobrecargará ese método. Lo único diferente será que puede hacerlo en aproximadamente 3 líneas en lugar de 5, porque no tendrá que crear la definición de clase derivada.

Si desea utilizar objetos simulados para aislar este comportamiento, debe dividir esta clase un poco. La lógica GetNextRenewalDate podría vivir fuera del objeto RenewalService .

El hecho de que se encuentre con este problema puede mostrar que aún queda por descubrir un diseño más simple o más fino. Encontrar una clase que sea un poco menos concreta, con un nombre como "administrador" o "servicio" es a menudo un indicio de que podría dividir su diseño en clases más pequeñas y obtener una mejor reutilización y facilidad de mantenimiento.


var mock = new Moq.Mock<RenewalService> { CallBase = true }; mock.Setup(m => m.GetNextRenewalDate(It.IsAny<Guid>())).Returns(null); var results = mock.Object.IsLastRenewalOfYear(...);