¿Cómo pruebo un método unitario que espera que un objeto se actualice a través de una referencia?

StackOverflow https://stackoverflow.com/questions/1424854

  •  07-07-2019
  •  | 
  •  

Pregunta

Tengo una unidad de problemas que prueba un método que cambia algunas propiedades de un tipo de referencia que se le pasa.

Como ejemplo, digamos que tengo una clase llamada Política.

Policy policy = new Policy();
policy.Status = Active;

Luego paso esta política al administrador de políticas para desactivarla.

policyManager.InactivatePolicy(policy);

El método de política de inactivación hace lo siguiente:

public void InactivatePolicy(Policy policy)
{
    policy.Status = Inactive;
    UpdatePolicy(policy); //saves the updated policy details via nhibernate
}

Con lo que tengo problemas es con la unidad que prueba este método DoSomething. (ignore el hecho de que lo que hace en este ejemplo es inútil)

public void DoSomething(Policy policy)
{
    Policy policy = new Policy();
    policy.Status = Active;

    policyManager.InactivatePolicy(policy);
}

Debido a que me burlo de Policy Manager, el estado no se establece en inactivo y como resultado cuando afirmo que después de DoSomething se llama el estado del la política está inactiva Obtengo una falla de prueba ya que todavía está activa.

[Test]
public void TheStatusShouldBeInactiveWhenWeDoSomething()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    MyClass mc = new MyClass(policyManagerMock.Object);

    Policy policy = new Policy();
    policy.Status = Active;

    mc.DoSomething(policy);

    Assert.That(policy.Status, Is.EqualTo(Inactive)); //this fails      
}

Así que estoy en una situación en la que el código funciona en realidad, pero no cuando está aislado en mis pruebas unitarias.

La única forma en que he podido solucionar este problema es hacer que el método InactivatePolicy del administrador de políticas devuelva el modificado política para que pueda simular el valor de retorno esperado.

public Policy InactivatePolicy(Policy policy)
{
    policy.Status = Inactive;
    UpdatePolicy(policy); //saves the updated policy details via nhibernate
    return policy;
}

[Test]
public void TheStatusShouldBeInactiveWhenWeDoSomething()
{
    Mock<IPolicyManager> policyManagerMock = new Mock<PolicyManager>();
    MyClass mc = new MyClass(policyManagerMock.Object);

    Policy expectedInactivePolicy = new Policy();
    expectedInactivePolicy.Status = Inactive;

    Policy policy = new Policy();
    policy.Status = Active;

    policyManagerMock
        .Setup(p => p.InactivatePolicy(policy))
        .Returns(expectedInactivePolicy);   

    mc.DoSomething(policy);

    Assert.That(policy.Status, Is.EqualTo(Inactive)); //this now succeeds

}

Por lo general, cuando estoy luchando para hacer una prueba unitaria de algo, es una indicación de que estoy haciendo las cosas mal.

¿Alguien sabe si hay una mejor manera de hacerlo? ¿Se obliga esencialmente a devolver valores que originalmente estaban destinados a ser actualizados mediante el valor de referencia que se pasó al método?

¿Es posible que mi problema sea que el administrador de políticas no debería tener un método InactivatePolicy sino que debería estar en el objeto de Política en sí y en la actualización de la base de datos llamada más tarde?

¿Fue útil?

Solución

No debería burlarse del PolicyManager, debería burlarse del método UpdatePolicy ya que aún desea probar la funcionalidad del método DoSomething.

Además, probablemente esté probando demasiado alto en el árbol.

Debe probar el método InactivatePolicy () de forma aislada y probar solo que la funcionalidad está funcionando y luego debe probar el método DoSomething (), nuevamente en Aislamiento.

Aquí tiene 2 unidades de código separadas y debe realizar pruebas unitarias que prueben cada unidad específicamente.

Otros consejos

Rambling

No entiendo del todo.

Si no está probando el hecho de que se establece en true a través de NHibernate (es decir, va a suponer que funciona), entonces, ¿qué está probando? ¿Por qué molestarse en probar, en absoluto, que el valor se establece, dado que en el código de producción simplemente asumirá que es así? Incluso si se burlara trivialmente de un sistema que lo establece como verdadero, no veo el punto, porque no es lo mismo que el código de producción.

En el mejor de los casos, consideraría tener un almacén de datos 'burlón'; no hibernate, eso simplemente no hace nada. En este caso, se implementaría en la clase UpdatePolicy , con algo de 'MockRepo' en lugar de 'nHibernateRepo'.

De esta manera, si configura el repositorio adecuadamente, podría ver que se está configurando.

Aunque me pregunto cuál es el punto, porque tal vez su código nHibernate tiene un error, y efectivamente todo lo que está comprobando es la configuración de un booleano.

Summary

¿Por qué no solo tener un db de desarrollo de prueba con el que puedas ejecutar esta prueba?

Creo que la prueba es incorrecta porque en realidad está probando el objeto simulado y su efecto en el estado activo de su objeto de política en lugar de probar su objeto original e incluso si la prueba pasa en el escenario del mundo real PolicyManager puede comportarse de manera diferente y causar DoSomething fallar Tal vez sea mejor que pruebe PolicyManager y su método UpdateInactive en una prueba unitaria y tenga un prueba de integridad para probar DoSomething junto con el PolicyManager real.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top