Pregunta

Burlándose de clases cerradas puede ser un dolor.Yo actualmente a favor de un Modelo de adaptador para controlar esto, pero algo acerca de solo mantiene siente extraño.

Así que, ¿Cuál es la mejor manera de burlarse de clases cerradas?

Java respuestas son más que bienvenidos.De hecho, preveo que la comunidad de Java ha estado lidiando con este largo y tiene mucho que ofrecer.

Pero aquí están algunos de los .NET opiniones:

¿Fue útil?

Solución

Mi regla general es que los objetos que necesito para burlarse debe tener una interfaz común también.Creo que esto es justo lo que respecta al diseño y hace pruebas mucho más fácil (y, generalmente, es lo que se obtiene si hacer TDD).Más información sobre esto se puede leer en los exámenes de Google Blog último mensaje (Ver punto 9).

También, he estado trabajando principalmente en Java en los últimos 4 años y puedo decir que puedo contar con una mano el número de veces que me he creado una final (sellado) de la clase.Otra regla aquí es que siempre debe tener una buena razón para sellar una clase, en contraposición a sellar de forma predeterminada.

Otros consejos

Para .NET, usted podría usar algo como TypeMock, que utiliza el perfil de la API y permite gancho en llamadas a casi cualquier cosa.

Yo creo que Los lunares, de Microsoft Research, le permite hacer eso.A partir de los Moles de la página:

Los lunares pueden ser utilizados para cualquier desvío .NET método, incluyendo la no-virtual/estático métodos de sellado tipos.

ACTUALIZACIÓN: hay un nuevo marco llamado "Fakes" en las próximas VS 11 versión que está diseñado para reemplazar los Lunares:

El El Marco de las falsificaciones en Visual Studio 11 es la próxima generación de los Topos y Comprobantes, y eventualmente la reemplace.Falsificaciones es diferente de la de los Lunares, sin embargo, hasta el movimiento de Moles a las Falsificaciones se requieren algunas modificaciones a su código.Una guía para esta migración estará disponible en una fecha posterior.

Requisitos:11 De Visual Studio Ultimate .NET 4.5

El problema con TypeMock es que las excusas de un mal diseño.Ahora, yo sé que es a menudo alguien más mal diseño que se esconden, pero permitir que en su proceso de desarrollo puede llevar muy fácilmente a permitir que su propio mal diseños.

Creo que si vas a utilizar un marco de trabajo ficticios, usted debe utilizar una tradicional (como Moq) y crear una capa de aislamiento alrededor de la unmockable cosa, y se burlan de la capa de aislamiento en su lugar.

Yo casi siempre de evitar que las dependencias de clases externas profundo dentro de mi código.En lugar de eso, prefiero usar un adaptador/puente para hablar con ellos.De esa manera, estoy lidiando con mi semántica, y el dolor de la traducción es aislado en una clase.

También hace que sea más fácil cambiar mi dependencias en el largo plazo.

Me encontré con este problema recientemente y después de leer y buscar en la web, parece que no hay ninguna manera fácil de todo, excepto para el uso de otra herramienta como se mencionó anteriormente.O crudo de manejar las cosas como yo:

  • Crear una instancia de la clase cerrada sin llegar constructor llamado.
  • Sistema.En tiempo de ejecución.La serialización.FormatterServices.GetUninitializedObject(instanceType);

  • Asignar valores a sus propiedades o campos a través de la reflexión

  • YourObject.GetType().GetProperty("PropertyName").SetValue(dto, newValue, null);
  • YourObject.GetType().GetField("FieldName").SetValue(dto, newValue);

Yo por lo general a tomar el camino de la creación de una interfaz de adaptador y/clase de proxy para facilitar la burla del tipo sellado.Sin embargo, también he experimentado con saltarse la creación de la interfaz y hacer el tipo de proxy no sellado con métodos virtuales.Esto funcionó bien cuando el proxy es realmente una base natural de la clase que encapsula y los usuarios de parte de la clase cerrada.

Cuando se trata con el código que requiere esta adaptación, me cansé de realizar las mismas acciones para crear la interfaz y el tipo de proxy por lo que he implementado una biblioteca para automatizar la tarea.

El código es un poco más sofisticado que el ejemplo dado en el artículo de referencia, ya que se produce una asamblea (en vez de código fuente), permite la generación de código para ser realizado en cualquier tipo, y no requiere mucho de la configuración.

Para obtener más información, por favor consulte esta página.

Es perfectamente razonable para burlarse de una clase cerrada debido a que muchas marco clases están sellados.

En mi caso estoy tratando de burlarse .Net MessageQueue clase para que yo pueda TDD mi agraciado excepción lógica de control.

Si alguien tiene ideas sobre cómo superar Moq del error con respecto a "no Válido de la instalación de un no-reemplazable miembro", por favor hágamelo saber.

código:

    [TestMethod]
    public void Test()
    {
        Queue<Message> messages = new Queue<Message>();
        Action<Message> sendDelegate = msg => messages.Enqueue(msg);
        Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate =
            (v1, v2) =>
            {
                throw new Exception("Test Exception to simulate a failed queue read.");
            };

        MessageQueue mockQueue = QueueMonitorHelper.MockQueue(sendDelegate, receiveDelegate).Object;
    }
    public static Mock<MessageQueue> MockQueue
                (Action<Message> sendDelegate, Func<TimeSpan, MessageQueueTransaction, Message> receiveDelegate)
    {
        Mock<MessageQueue> mockQueue = new Mock<MessageQueue>(MockBehavior.Strict);

        Expression<Action<MessageQueue>> sendMock = (msmq) => msmq.Send(It.IsAny<Message>()); //message => messages.Enqueue(message);
        mockQueue.Setup(sendMock).Callback<Message>(sendDelegate);

        Expression<Func<MessageQueue, Message>> receiveMock = (msmq) => msmq.Receive(It.IsAny<TimeSpan>(), It.IsAny<MessageQueueTransaction>());
        mockQueue.Setup(receiveMock).Returns<TimeSpan, MessageQueueTransaction>(receiveDelegate);

        return mockQueue;
    }

Aunque actualmente sólo está disponible en versión beta, creo que vale la pena teniendo en cuenta el calza característica de la nueva El marco de las falsificaciones (parte de la Visual Studio 11 Versión Beta).

Calza tipos de proporcionar un mecanismo para cualquier desvío .Método de RED a un usuario definido delegado.Calza tipos de código generado por el Falsificaciones generador, y que el uso de los delegados, que llamamos calza tipos, para especificar el nuevo método de implementaciones.Bajo el capó, shim tipos de uso de las devoluciones de llamada que fueron inyectados en tiempo de ejecución en el método de MSIL cuerpos.

Personalmente yo estaba buscando en el uso de este para burlarse de los métodos de sellado marco de las clases, tales como DrawingContext.

Es allí una manera de implementar una clase cerrada de una interfaz...y se burlan de la interfaz de lugar?

Algo en mí se siente que el tener clases cerradas que está mal en el primer lugar, pero eso es sólo conmigo :)

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