This is a re-post from an old blog I had dated 2010, it has some useful information:
Recently I have been busy working on a large unmanaged Visual C++ project and I needed to introduce unit testing. I decided to create a Managed C++/CLI library with a few assert wrappers, so I could drive the testing via NUnit.
Another option, especially for testing individual components, is to create a C++/CLI class which inherits from the unmanaged class you would like to test. This allows you to test from C#.
Here is my project being testing via the Managed C++/CLI Library:

One of the issues with using native C++ in CLI/C++ is the marshaling of strings, such as between std::wstring and System^. To address this I created a base class which provided functions to marshal the strings, and wrappers around the NUnit StringAssert class:
static std::string AsString(String ^s){
std::string os;
MarshalString(s,os);
return os;
}
static std::string AsWString(String ^s){
std::string os;
MarshalString(s,os);
return os;
}
static void MarshalString(String^ s, std::string& os){
using namespace Runtime::InteropServices;
const char* chars=(const char*)(Marshal::StringToHGlobalAnsi(s)).ToPointer();
os=chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
static void MarshalString(String^ s, std::wstring& os){
using namespace Runtime::InteropServices;
const wchar_t* chars=(const wchar_t*)
(Marshal::StringToHGlobalUni(s)).ToPointer();
os=chars;
Marshal::FreeHGlobal(IntPtr((void*)chars));
}
static void StringAssertContains(String^ expected, const std::string & actual){
String^ a=gcnew String(actual.c_str());
StringAssert::Contains(expected,a);
}
// etc….
To simplify testing, I decided to create a test database and between tests attach and detach the database, ensuring I was always testing from a known baseline. This required two things, first batch and SQL files to do the attaching/detaching:
AttachDatabase.cmd
copy /Y c:\db\TestBase.mdf c:\db\Test.mdf
sqlcmd -S STFERDINAND\SqlExpress -U sa -P p@ssw0rd -i c:\db\AttachDatabase.sql
AttachDatabase.sql
USE [master]
GO
CREATE DATABASE [TestDatabase] ON
( FILENAME = N’C:\db\Test.mdf’ ) FOR ATTACH ;
GO
DetachDatabase.cmd
sqlcmd -S STFERDINAND\SqlExpress -U sa -P p@ssw0rd -i c:\db\DetachDatabase.sql
del c:\db\Test.mdf
DetachDatabase.sql
USE [master]
GO
DROP DATABASE [TestDatabase]
GO
And secondly, a base test fixture to execute these commands:
[SetUp]
void TestSetup(void){
InitializeDatabase();
}
[TearDown]
void TestTeardown(void){
FinalizeDatabase();
}
void InitializeDatabase(void){
system(AsString(CreateDatabaseScript).c_str());
Domain.Initialize();
}
void FinalizeDatabase(void){
Domain.Finalize();
system(AsString(DeleteDatabaseScript).c_str());
}
And finally, with the infrastructure in place, it’s on to creating test fixtures:
[TestFixture]
public ref class AvatarServiceFixture:BaseFixture{
public:
[Test]
void LoadAvatarTest(void){
CallResult<Avatar> avatarResult=AvatarService::GetAvatar(PLAYER1_ID);
Assert::IsTrue(avatarResult.IsSuccess());
Avatar & avatar=avatarResult.Value;
vector<AvatarObject> avatarObjects
=AvatarObject::GetByAvatarId(avatar.GetId());
AvatarObjectFilter aoFilter(avatarObjects);
AvatarObjectFilter activeObjects=aoFilter.WhereIsActive(true);
CheckTransientActive(activeObjects,avatar.GetTop());
CheckTransientActive(activeObjects,avatar.GetAccessory());
// etc...
}
}
That’s pretty much it in a nutshell.
You can find more out about the excellent NUnit from their official site.