2009-09-18 8 views
3

Je souhaite créer un projet de test unitaire C++ géré pour tester un projet MFC non géré. J'ai lu la procédure de msujaws et je l'ai suivie. Je mis en œuvre une méthode d'essai pour tester la chaîne de retour d'une fonction comme ceci:Test d'unité C++ non géré dans Visual Studio 2008

#include "stdafx.h" 
#include "TxStats.h" 
#include <cstdlib> 
#include <atlstr.h> 

#pragma managed 

#using <mscorlib.dll> 
#using <System.dll> 
#using <system.data.dll> 

using namespace std; 
using namespace System; 
using namespace System::Text; 
using namespace System::Text::RegularExpressions; 
using namespace System::Collections::Generic; 
using namespace System::Runtime::InteropServices; 
using namespace Microsoft::VisualStudio::TestTools::UnitTesting; 

namespace AUnitTest 
{ 
    [TestClass] 
    public ref class TxStatsTest 
    { 
    private: 
     TestContext^ testContextInstance; 

    public: 
     /// <summary> 
     ///Gets or sets the test context which provides 
     ///information about and functionality for the current test run. 
     ///</summary> 
     property Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ TestContext 
     { 
      Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ get() 
      { 
       return testContextInstance; 
      } 
      System::Void set(Microsoft::VisualStudio::TestTools::UnitTesting::TestContext^ value) 
      { 
       testContextInstance = value; 
      } 
     }; 

     #pragma region Additional test attributes 
     // 
     //You can use the following additional attributes as you write your tests: 
     // 
     //Use ClassInitialize to run code before running the first test in the class 
     //[ClassInitialize()] 
     //static void MyClassInitialize(TestContext^ testContext) {}; 
     // 
     //Use ClassCleanup to run code after all tests in a class have run 
     //[ClassCleanup()] 
     //static void MyClassCleanup() {}; 
     // 
     //Use TestInitialize to run code before running each test 
     //[TestInitialize()] 
     //void MyTestInitialize() {}; 
     // 
     //Use TestCleanup to run code after each test has run 
     //[TestCleanup()] 
     //void MyTestCleanup() {}; 
     // 
     #pragma endregion 

     [TestMethod] 
     void TestGetTxRateStr() 
     { 
      /* str to CString 

       CManagedClass* pCManagedClass = new CManagedClass(); 
       pCManagedClass->ShowMessage(strMessage); 

       char* szMessage = (char*)Marshal::StringToHGlobalAnsi(strMessage); 
       CUnmanagedClass cUnmanagedClass; cUnmanagedClass.ShowMessageBox(szMessage); 
       Marshal::FreeHGlobal((int)szMessage); 

      */ 
      CString out = TxStats::GetTxRateStr(1024); 
      // convert between MFC and .NET String implementations 
      String^myManagedString = Marshal::PtrToStringAnsi((IntPtr) (char *) out.GetBuffer()); 
      String^ret = myManagedString ;///gcnew String(); 
      Regex^matStr = gcnew Regex("1024 KB/s"); 
      StringAssert::Matches(ret, matStr); 
     } 
    }; 
} 

qui teste le code dans un autre projet qui ressemble à ceci:

#include "stdafx.h" 
#include "TxStats.h" 

TxStats::TxStats() 
{ 
} 
/* 
This method returns a data rate string formatted in either Bytes, KBytes, MBytes or GBytes per sec 
from an int of the bytes per second. 
*/ 
CString TxStats::GetTxRateStr(__int64 Bps) 
{ 
enum DataUnits dunit; 
const __int64 dataSizes[]= { 0x1,  // 2^0 
     0x400,  // 2^10 
     0x100000, // 2^20 
     0x40000000};// 2^30 
const char *dataStrs[] = { "B/s", 
      "KB/s", 
      "MB/s", 
      "GB/s"}; 
CString out; 
double datarate; 
bool finish = false; 
for (dunit = A_KBYTE; dunit <= LARGER_THAN_BIGGEST_UNIT; dunit = DataUnits(dunit+1)) 
{ 
    if (dunit == LARGER_THAN_BIGGEST_UNIT) 
    { 
    if (dataSizes[dunit - 1] <= Bps) 
    { 
    //Gigabytes/sec 
    datarate = Bps/((double) dataSizes[dunit - 1]); 
    out.Format("%4.2f %s", datarate, dataStrs[dunit - 1]); 
    finish = true; 
    break; 
    } 
    } 
    else 
    { 
    if (Bps < dataSizes[dunit]) 
    { 
    //(Kilo, Mega)bytes/sec 
    datarate = Bps/((double) dataSizes[dunit - 1]); 
    out.Format("%4.2f %s", datarate, dataStrs[dunit - 1]); 
    finish = true; 
    break; 
    } 
    } 
} 
if (! finish) 
{ 
    out.Format("%s", "Unknown!"); 
} 
return out.GetBuffer(); 
} 


void TxStats::BytesToSizeStr(__int64 bytes, CString &out) 
{ 
if (bytes < 0) 
{ 
    out = "Err"; 
} 
else if (bytes == 0) 
{ 
    out = "0B"; 
} 
else 
{ 
    CString size; 
    CString byteChar = "B"; 
    CString unit; 
    int val; 
    if (bytes < 1024) 
    { 
    //Bytes 
    unit = ""; 
    val = (int)bytes; 
    } 
    else if ((bytes >> 10) < 1024) 
    { 
    //Kilobytes 
    unit = "K"; 
    __int64 div = 1 << 10; 
    val = (int) (bytes/((double) div)); 
    } 
    else if ((bytes >> 20) < 1024) 
    { 
    //Megabytes 
    unit = "M"; 
    __int64 div = 1 << 20; 
    val = (int) (bytes/((double) div)); 
    } 
    else 
    { 
    //Else assume gigabytes 
    unit = "G"; 
    __int64 div = 1 << 30; 
    val = (int) (bytes/((double) div)); 
    } 
    unit = unit + byteChar; 
    const char * unitCharBuf = unit.GetBuffer(); 
    size.Format("%d%s", ((int) val), unitCharBuf); 
    out = size.GetBuffer(); 
} 

} 

Cependant, quand je compile ce code Je reçois l'erreur suivante:

2>TxStatsTest.obj : error LNK2028: unresolved token (0A0005D4) "public: static class ATL::CStringT<char,class StrTraitMFC_DLL<char,class ATL::ChTraitsCRT<char> > > __cdecl TxStats::GetTxRateStr(__int64)" ([email protected]@@[email protected][email protected][email protected]@[email protected]@@@@[email protected]@[email protected]) referenced in function "public: void __clrcall AUnitTest::TxStatsTest::TestGetTxRateStr(void)" ([email protected]@[email protected]@$$FQ$AAMXXZ) 
2>TxStatsTest.obj : error LNK2019: unresolved external symbol "public: static class ATL::CStringT<char,class StrTraitMFC_DLL<char,class ATL::ChTraitsCRT<char> > > __cdecl TxStats::GetTxRateStr(__int64)" ([email protected]@@[email protected][email protected][email protected]@[email protected]@@@@[email protected]@[email protected]) referenced in function "public: void __clrcall AUnitTest::TxStatsTest::TestGetTxRateStr(void)" ([email protected]@[email protected]@$$FQ$AAMXXZ) 
2>\trunk\<proj>\Debug\AUnitTest.dll : fatal error LNK1120: 2 unresolved externals 
2>Caching metadata information for c:\program files\microsoft visual studio 9.0\common7\ide\publicassemblies\microsoft.visualstudio.qualitytools.unittestframework.dll... 
2>Build log was saved at "file://trunk\<proj>\AUnitTest\Debug\BuildLog.htm" 
2>AUnitTest - 3 error(s), 0 warning(s) 
========== Rebuild All: 1 succeeded, 1 failed, 0 skipped ========== 

quelqu'un peut-il expliquer pourquoi le projet de test unitaire pourrait ne pas être contre les relier fichiers OBJ du projet principal? (Je l'ai déjà précisé le principal projet en tant que dépendance du projet de test unitaire)

+0

Est-ce que l'une des réponses fournies d'aide? – Jared

Répondre

3

Vous pouvez ajouter

#pragma comment(lib, "TxStats.lib") 

au stdafx.cpp de votre projet de test unitaire pour relier contre l'autre bibliothèque.

+0

que se passe-t-il s'il n'est pas construit en .lib mais en .obj (ou puis-je le changer en .lib en gardant à l'esprit que mon autre projet est une application et doit le rester). – Jay

+1

Vous pouvez générer une bibliothèque d'importation .lib sans affecter quoi que ce soit d'autre. Spécifiez simplement un nom de fichier sur la page Avancé des options du lieur pour votre projet. –

2

Vous devez ajouter les fichiers * .obj du projet que vous souhaitez tester aux entrées de liaison du projet de test unitaire