¿Cuáles son las formas de probar la unidad de un patrón Singleton en C++? (con ejemplos, por favor)¿Cómo probar la unidad Singleton class - C++?
Respuesta
Haga que la implementación del singleton sea una clase separada, y haga un contenedor que implemente la "singletonness" fuera. De esa manera se puede probar la aplicación tanto como te gusta (excepto el comportamiento Singleton, que es trivial e innecesario.
class SingletonImpl {
public:
int doit(double,double);
};
class Singleton {
public:
Singleton& instance() {...}
int doit(double a,double b) {impl->doit(a,b);}
...
private:
SingletonImpl impl;
}
Un singleton es solo una clase de la cual solo puede tener una instancia. Cómo se encuentra esa instancia no es parte de ese patrón, por lo que el uso de DI con un singleton está completamente bien.
La prueba de la unidad del patrón de singleton es difícil, ese es uno de los principales argumentos en contra de su uso. Una forma de hacerlo en C++ es tener la definición de singleton en una unidad de compilación separada, para que pueda vincularse con una implementación simulada al probar las clases que usan el singleton.
¿Puedes mostrar un pequeño ejemplo aquí? –
Ésta es la forma en que lo haría
class Singleton
{
protected:
static Singleton *instance = 0:
public:
Singleton &GetInstance()
{
if (!instance) instance = new Singleton;
return *instance;
}
...
};
Luego de probar me gustaría crear sólo para propósitos de prueba
class TestSingleton : public Singleton
{
public:
void DestroyInstance() {
if (instance) delete instance;
instance = 0;
};
A continuación, utilice TestSingleton - por lo que son capaces de realizar todos los casos de prueba y asegúrese de que sea el comienzo en que se recrea la instancia.
¿No creaste el constructor privado? –
Ese es el bit '...' - Supuse que podrías completar esos bits. –
Pensé que fue deliberado por su parte. –
Supongamos que tenemos el anti-patrón singleton clásico, que es responsable de tres cosas:
class Singleton {
public:
// Globally accessible instance
static Singleton & instance();
// Public interface
void do_something();
private:
// Lifetime management
Singleton();
~Singleton();
}
y una clase que depende de esto:
class Dependent {
public:
Dependent() : s(Singleton::instance()) {}
void do_something_else();
private:
Singleton & s;
};
Ahora nos gustaría escribir una prueba unitaria para el singleton:
void test_singleton() {
Singleton s; // Problem 1
s.do_something();
assert(/* some post-condition */);
}
y para la clase dependiente:
struct StubSingleton : Singleton // Problem 2
{
int did_something;
StubSingleton : did_something(0) {}
void do_something() {++did_something;}
};
void test_dependent() {
StubSingleton s; // Problem 1
Dependent d(s); // Problem 3
d.do_something_else();
assert(s.did_something == 1);
}
Vemos que hay tres problemas que superar:
- No podemos crear y destruir los casos durante las pruebas;
- No podemos definir nuestras propias subclases para probar cómo se utiliza la interfaz;
- No podemos proporcionar nuestra propia dependencia a la clase dependiente.
La forma más fácil de superar estos problemas es refactorizar la clase Singleton:
- hacer público el constructor y el destructor, la responsabilidad de gestión de vida de la clase en movimiento;
- Haz que la interfaz sea abstracta, lo que nos permite definir nuestras propias implementaciones;
- Elimina la instancia global y modifica las clases dependientes para tomar su dependencia por referencia.
Así que ahora nuestras clases se parecen:
class Singleton {
public:
virtual ~Singleton() {}
virtual void do_something() = 0;
};
class RealSingleton : public Singleton
{
void do_something();
};
class Dependent {
public:
explicit Dependent(Singleton & s) : s(s) {}
void do_something_else();
private:
Singleton & s;
};
Ahora la clase es fácil de probar, y casi tan fácil de usar en la producción (sólo tiene que crear una instancia de RealSingleton
y pasar referencias donde se necesitan).El único problema es que ya no puedes llamarlo singleton.
Te daré seguimiento pronto, aquí y en tu otra respuesta. Gracias. –
- 1. C# Singleton Logging Class
- 2. ¿Cómo probar la unidad?
- 3. ¿Cómo probar la unidad NSCoding?
- 4. Cómo probar atributos de la unidad con MsTest usando C#?
- 5. Cómo probar la unidad de análisis JSON
- 6. Cómo probar la unidad HtmlHelper con Moq?
- 7. ¿Cómo puedo probar la unidad GC?
- 8. Cómo probar las subclases de la unidad
- 9. ¿Cómo puedo probar la unidad? ¿Es descartable?
- 10. ¿Cómo probar la unidad de su API?
- 11. Singleton Class que requiere alguna llamada asincrónica
- 12. Encuadernación para Singleton Class Observable Collection Miembro
- 13. Cómo probar la unidad de lógica de devolución de llamada?
- 14. ¿Cómo debo probar la unidad de un generador de código?
- 15. ¿Cómo puedo probar la unidad de un servicio de Windows?
- 16. Cómo probar la unidad con diferentes configuraciones en Django?
- 17. Cómo probar la lógica de la unidad en jsp?
- 18. Cómo probar las clases abstractas de unidad
- 19. Cómo probar el código sincronizado de la unidad
- 20. Usar Clojure para probar la unidad Java
- 21. ¿Cómo puedo probar la unidad correctamente mi DAL?
- 22. ¿Cómo puedo probar la unidad con jazmín y navegar?
- 23. ¿Cómo puedo probar la unidad de algo que utiliza VisualTreeHelper?
- 24. ¿Cómo probar las reglas comerciales de la unidad?
- 25. Cómo afirmar/probar la unidad de servidores Respuesta JSON?
- 26. ¿Cómo puedo probar la unidad First Framework Code First Mappings?
- 27. Cómo probar la unidad qt gráficos ver widgets/elementos
- 28. ¿Cómo puedo probar la unidad de mis migraciones de FluentMigrator?
- 29. Cómo simular DataReader para probar la unidad DAL
- 30. ¿Cómo puedo probar la unidad de un controlador Symfony2?
Esto se parece a dos preguntas bastante separados. Tal vez usted podría mover la parte de inyección de dependencia en una nueva pregunta? –
@GeorgFritzsche Se dice que la inyección de dependencia es una forma de probar la unidad, ¿no? –
"Inyectar un singleton en ..." y "probar una unidad de singleton" son dos temas diferentes. –