[Gelöst] Privaten Konstruktor im Test aufrufen



  • Hallo zusammen,

    ich möchte gerade mein C++ Programm testen und stoße dabei auf folgendes Problem. Ich habe viele Klassen mit privaten Konstruktoren, diese werden über eine statische Methode erzeugt. Nun will ich in meinem Test aber nur eine Instanz anlegen, daher müsste ich den privaten Konstruktor der Instanz aufrufen, doch leider klappt das nicht so wie ich es bisher gelesen habe:

    Klasse die ich z.B. testen will:

    #pragma once
    #include <string>
    #include <fstream>
    class UnitTest1;
    
    class Example
    {	
    	friend class UnitTest1;
    
    public:	
    	~Example() = default;
    	static const Example Create(std::fstream& stream)
    	{
    		// LESEN usw.
    		return Example("Hallo Welt");
    	};
    
    private:
    	friend class UnitTest1;
    	Example(std::string name){};
    };
    

    Test:

    #include "stdafx.h"
    #include "CppUnitTest.h"
    #include "../Projekt1/Example.h"
    
    using namespace Microsoft::VisualStudio::CppUnitTestFramework;
    
    namespace Projekt1Test
    {		
    	TEST_CLASS(UnitTest1)
    	{
    	public:
    
    		TEST_METHOD(TestMethod1)
    		{
    			Example example("Test");
    		}
    	};
    }
    

    Leider bekomme ich immer die Fehlermeldung

    Fehler C2248 "Example::Example": Kein Zugriff auf private Member, dessen Deklaration in der Example-Klasse erfolgte.

    Meine Vermutung ist es, dass es an TEST_CLASS(UnitTest1) liegt, aber wenn wüsste ich nicht, wie ich es zum Laufen bringe.

    Hat jemand vielleicht einen Ratschlag?

    Schöne Grüße
    Quaneu



  • Ich kenne mich mit dem Test-Framework nicht aus.
    Aber warum willst du nicht die static-Funktion benutzen? Ich vermute mal, dich stört wahrscheinlich, das mit Filestream gearbeitet wird? Dann ändere doch den Argumenttyp, einfach eine abstraktere Ebene: iostream. Man sollte sowieso so abstrakt wie möglich arbeiten.

    Wenn diese etwas macht, was für den Testfall "ungünstig" ist, dann schreib doch eine zweite static-Funktion, die testbar ist. Normalerweise sollten Klassen (wenn sie einem gehören) testbar geschrieben werden.

    Übrigens würde ich meine Klassen nicht von einem Test-Framework abhängig machen! Das ist ganz übles Design! 👎



  • Was macht TEST_CLASS konkret?



  • Ok, die Vorwärtsdekalartion ist nicht im namespace. Die echte Klasse ist daher kein Freund.



  • @Artchi:

    Weil ich in diesem Test nur eine Instanz brauche und nicht die statische Funktion testen will. Das Problem ist, dass diese Klassen aus einer binär Datei erzeugt werden, d.h. ich müsste für jeden Test, der etwas mit diesen Klassen zu tun hat eine binär Datei schreiben, dies ist aber sehr sehr Aufwendig.

    Übrigens würde ich meine Klassen nicht von einem Test-Framework abhängig machen! Das ist ganz übles Design! 👎

    Aus diesem Grund will ich eben nicht eine Methode einbauen, die nur in Tests aufgerufen wird. Daher wollte ich eben probieren über friend den privaten Konstruktor aufzurufen.

    @manni66:

    ///////////////////////////////////////////////////////////////////////////////////////////
    // Macro to define your test class. 
    // Note that you can only define your test class at namespace scope,
    // otherwise the compiler will raise an error.
    #define TEST_CLASS(className) \
    ONLY_USED_AT_NAMESPACE_SCOPE class className : public ::Microsoft::VisualStudio::CppUnitTestFramework::TestClass<className>
    
    // Force a macro to be used only at namespace scope:
    #define ONLY_USED_AT_NAMESPACE_SCOPE namespace  ___CUT___ {extern int YOU_CAN_ONLY_DEFINE_TEST_CLASS_AT_NAMESPACE_SCOPE;}
    


  • @mani66:

    Ok, die Vorwärtsdekalartion ist nicht im namespace. Die echte Klasse ist daher kein Freund.

    Danke für den Hinweis, habe es schon mit

    namespace Projekt1Test
    {
    	class  UnitTest1;
    }
    

    probiert, jedoch ist in ONLY_USED_AT_NAMESPACE_SCOPE noch einer, den ich aber leider nicht verstehe...



  • Und auch

    friend class Projekt1Test::UnitTest1;
    

    ?
    (s.a. Friending/Using a class in a different namespace)

    Das Makro kannst du ignorieren, da es nur eine Fehlermeldung erzeugt, wenn es nicht innerhalb eines 'namespace' deklariert ist.



  • Vielen vielen Dank. Dann klappt es auch. 👍 👍 👍


Log in to reply