I am trying to mock an Open function present as part of the CDatabase Class by using Google Mock. Visual studio version: 2010
Below is the code snippet:
class TestRLanguage: public RLanguage, public ::testing::Test
{
};
class FakeDatabase : public CDatabase
{
public:
MOCK_METHOD5(Open_impl, BOOL(LPCTSTR lpszDSN, BOOL bExclusive,BOOL bReadonly, LPCTSTR lpszConnect,BOOL bUseCursorLib));
BOOL Open(LPCTSTR lpszDSN, BOOL bExclusive = FALSE,
BOOL bReadonly = FALSE, LPCTSTR lpszConnect = _T("ODBC;"),
BOOL bUseCursorLib = TRUE) override
{
Open_impl( lpszDSN, bExclusive, bReadonly, lpszConnect, bUseCursorLib);
}
};
// Test case for testing initialize function
TEST_F(TestRLanguage, initializeSuccess)
{
FakeDatabase database;
EXPECT_CALL(database, Open(NULL, FALSE, FALSE, "ODBC;DSN=", FALSE)).Times(testing::Exactly(1));
}
I get the below error:
error C2770: invalid explicit template argument(s) for 'AddReference<const ::std::tr1::tuple_element<I,std::tr1::tuple<_Arg0,_Arg1,_Arg2,_Arg3,_Arg4>>::type>::type testing::internal::TuplePolicy<TupleT>::get(const std::tr1::tuple<_Arg0,_Arg1,_Arg2,_Arg3,_Arg4> &)' c:\src\googlemockandtest\aqtsw\util\googletest\googletest-release-1.8.1\googletest\include\gtest\gtest-printers.h
Can anyone help me in solving this problem?
I had the same issue. In my case it was related to the version of Google Test. I had the issue with version 1.8.1 -- "the last release supporting pre-C++11 compilers" (as stated here). The issue was fixed with pull request #1817. I am using HEAD of branch 1.8.x now (commit dea0216) and the issue is gone.
There are two errors in your test:
you put in the EXPECT_CALL a method function, that is not a mock method
you do not call any method in your test.
This is a proper way:
TEST_F(TestRLanguage, initializeSuccess)
{
FakeDatabase database;
EXPECT_CALL(database, Open_impl(NULL, FALSE, FALSE, "ODBC;DSN=", FALSE)).Times(testing::Exactly(1));
database.Open(NULL);
}
Related
To start off, I am working with 3ds Max SDK. I don't expect many people to have used this SDK but the issue itself is not SDK specific from what I can tell. I suspect this is a Visual Studio issue but I'm not sure how to fix.
Here is a section the code that is currently showing the error.
#include <actiontable.h>
namespace {
const ActionTableId creatorToolActionTableId = 0x52510afc; //1381042940
const ActionContextId creatorToolActionContextId = 0x59b927b6;
}
// Setting up the Creator Tool ActionTable
class CreatorToolActionTable : public ActionTable {
public:
CreatorToolActionTable()
: ActionTable(creatorToolActionTableId, creatorToolActionContextId, TSTR(GetString(IDS_CT_CATEGORY)))
{
static ActionDescription ctActions[] = {
//Creator Tool 1
{
ID_CREATOR_TOOL,
IDS_CREATOR_TOOL_DESC,
IDS_CREATOR_TOOL,
IDS_CT_CATEGORY,
},
//Creator Tool Help 2
{
ID_CREATOR_TOOL_HELP,
IDS_CREATOR_TOOL_HELP_DESC,
IDS_CREATOR_TOOL_HELP,
IDS_CT_CATEGORY
}
};
BuildActionTable(nullptr, sizeof(ctActions) / sizeof(ctActions[0]), ctActions, hInstance);
};
~CreatorToolActionTable() {};
BOOL IsEnabled(int) override { return TRUE; };
BOOL IsChecked(int) override { return FALSE; };
};
The error is showing at ActionTable(creatorToolActionTableId, creatorToolActionContextId, TSTR(GetString(IDS_CT_CATEGORY))).
The error is the same as the title that there is not a constructor for ActionTable::ActionTable matching the arguments (const ActionTableId, const ActionContextId, WStr).
When referring to the SDK documents and examples of code, there is maxMenuDemo which is my main reference for this. The section of code in maxMenuDemo.cpp is:
#include <actiontable.h>
namespace {
const ActionTableId kMenuDemoActionTableId = 0x44370c39;
const ActionContextId kMenuDemoActionContextId = 0x44370c3A;
}
class MenuDemoActionTable : public ActionTable
{
public:
MenuDemoActionTable()
: ActionTable(kMenuDemoActionTableId, kMenuDemoActionContextId, TSTR(GetString(IDS_AT_CATEGORY)))
{
// You can comment this out, if you want to load files from disk.
RegisterDynamicResources(GetColorManager()->GetAppFrameColorTheme());
// This packages up our actions into an ActionDescription for our ActionTable
static ActionDescription spActions[] = {
ID_ACTION1, // ID
IDS_ACTION1_DESC, // menu1
IDS_ACTION1,
IDS_AT_CATEGORY,
ID_ACTION2,
IDS_ACTION2_DESC,
IDS_ACTION2,
IDS_AT_CATEGORY };
BuildActionTable(nullptr, sizeof(spActions) / sizeof(spActions[0]), spActions, hInstance);
};
~MenuDemoActionTable()
{
UnregisterDynamicResources();
};
MaxIcon* GetIcon(int cmdId) override;
BOOL IsChecked(int /*cmdId*/) override { return FALSE; };
BOOL IsEnabled(int /*cmdId*/) override { return TRUE; };
// Qt support for loading icon resources
using Theme = IColorManager::AppFrameColorTheme;
void RegisterDynamicResources(const Theme& theme = Theme::kDarkTheme);
void UnregisterDynamicResources();
private:
std::unique_ptr<MaxIcon> m_MaxIcons[2];
// The registered path for the compiled icon bundles - see the maxMenuDemo.qrc
// files, and the custom build tool on the file on how these .rcc files
// are being generated.
QString m_registeredRCCPath;
};
To me, the code is the exact same in terms of what is being input for CreatorToolActionTable : Actiontable(creatorToolActionTableId, creatorToolActionContextId, TSTR(GetString(IDS_CT_CATERGORY))) and for MenuDemoActionTable(): ActionTable(kMenuDemoActionTableId, kMenuDemoActionContextId, TSTR(GetString(IDS_AT_CATEGORY))). Therefore, I would assume it would work for my code and I should not have the error since the template code also does not have the error.
The only real differences between my code and the template is I have removed references to Qt and icons as I am not using them.
There are two constructors for ActionTable:
CoreExport ActionTable(ActionTableId id, ActionContextId contextId, MSTR& name) and
CoreExport ActionTable(ACtionTableId id, ActionContextId contextId, MSTR& name, HACCEL hDefaults, int numids, ActionDescription* pOps, HINSTANCE hInst)
I have tried using the second constructor as well on its own and received the same errors when the parameters matched the documentation.
Here is the link to the SDK documentation (specifically for ActionTable class): 3ds Max 2021 SDK
I am running this on VS2019 targeted for VS2015.
Is the issue with VS2019 or am I completely missing something?
So I am trying to write test cases for my production code but the coverage is drastically low due to the usage of some external C library which cannot be executed without target hardware, So I have no choice but to stub the same. Now the problem is how to stub a C function ?
My production code : prod_code.cpp
int TargetTestClass::targetFunc()
{
if(externalCFunc() == True)
{
statement1; statement2; statement3; /// and so on
}
}
My testcode.cpp generally contains tests like this
//Fixture for Target Test class
class TargetTestClassFixture : public testing::Test {
TargetTestClass* targetTestClassPtr;
void SetUp() {
targetTestClassPtr = new TargetTestClass();
}
void TearDown() {
delete targetTestClassPtr;
}
};
TEST_F (unitTest, test_001)
{
targetTestClassPtr->targetFunc(); //Need to do something here so that externalCFunc() returns true on call
}
What you can do is to create a source file like my_c_stubs.c where you rudimentary implement your C function. For example, the implementation can just return true. Then don't link original source file with the external C function but rather use your stub file. You should still use the original C header. In this way you won't be able to stub inline functions though. If it is required, some more sophisticated approach is needed.
I found 2 solutions to my problem so I am going to answer the same here.
Solution 1 : This involved changing the target source code. Basically you need to write a wrapper that calls the external C functions like below
Class TargetTestClass{
protected:
int targetFunc();
virtual int externalCFuncWrapper(); // Wrapper
};
//call the external C function from the wrapper
int TargetTestClass::externalCFunctionWrapper(){
return(externalCFunc());
}
//Definition of targetFuc in original question
//Now write a mock class for Target Test Class as usual and mock the wrapper function to return what you want to
class MockTargetTestClass : public TargetTestClass{
public: MOCK_METHOD0(externalCFunctionWrapper, int());
};
//Now use the Mock class as needed
TEST_F ( TargetUnitTest, TestingExternalCFuctionCall)
{
MockTargetTestClass mockTargetTestClassObj;
using ::testing::Return;
using ::testing::_;
Expect_Call(mockTargetTestClassObj, externalCFunctionWrapper())
.WillOnce(Return(1));
Assert_EQ(mockTargetTestClassObj.targetFunc(), 1);
}
Solution 2 : Thanks to #kreynolds, I have looked into Fake Function Framework and implemented as follows :
Class TargetTestClass{
protected:
int targetFunc();
//No Code change needed in target source code
};
//In testcode.cpp
#include <gmock-global/gmock-global.h>
MOCK_GLOBAL_FUNC0(externalCFunc, int());
TEST( Unittest, test002){
using ::testing::Return;
using ::testing::_;
EXPECT_GLOBAL_CALL(externalCFunc, externalCFunc()).WillOnce(Return(1));
TargetTestClass targetFunc; //This does not contain any wrapper
EXPECT_EQ(targetTestClassObj.targetFunc(), 1);
}
I am using the second solution as this does not require any change in my source code and easier to use.
Once again thank you everyone for giving your time.
TL;DR: You can use GMock to add mocking capability to your Microsoft native c++ unit tests. See my answer below for details.
I want to start adding mocks to my existing set of native unit tests. The tests are written using Microsoft's CppUnitTestFramework framework, which doesn't have support for mocking. I don't really want to convert the entire test suite to another framework just to add a few mocks.
Google's GMock framework seems to provide everything I need and the documentation suggests it can be used with frameworks other than gtest. So using advice from blog posts like this one, I created a couple of unit tests.
TEST_MODULE_INITIALIZE(ModuleInitialize)
{
// Enable google mock
GTEST_FLAG(throw_on_failure) = true;
int argc = 0;
TCHAR **argv = nullptr;
InitGoogleMock(&argc, argv);
}
TEST_CLASS(GMockTests)
{
public:
MockTestClass _mockObj;
TEST_METHOD(Method1_ParamIsOne_Method2CalledWithOne)
{
EXPECT_CALL(_mockObj, Method2(1)).Times(1);
_mockObj.Method1(1);
}
TEST_METHOD(Method1_ParamIsZero_IntentionallyFail)
{
// Expectation will fail
EXPECT_CALL(_mockObj, Method2(1)).Times(1);
_mockObj.Method1(0);
}
};
The results are less than satisfactory. The expectations do work (first method passes), but if any expectation fails the entire run is aborted with only the following unhelpful message in the test output:
[3/27/2019 11:39:17 AM Error] The active test run was aborted. Reason:
[3/27/2019 11:39:17 AM Informational] ========== Run test finished: 0 run (0:00:22.3042194) ==========
The Visual Studio Test Explorer window doesn't indicate what the problem is either. It just shows that one test succeeded and the other one didn't run:
So what I'm looking for from this integration is:
A GMock test failure doesn't abort the entire run.
Tests that fail GMock expectations are shown as failed.
All GMock messages should be shown in the test output.
I was able to get GMock working correctly with the CppUnitTestFramework by creating a custom TestEventListener. I then created a simple set of interface functions to make it easier to work with.
I used the gmock 1.7.0 NuGet package to install the GMock framework into my project, and added the two files shown below.
GMockUtils.h
#pragma once
#include <CppUnitTest.h>
#include <gmock/gmock.h>
namespace testing {
namespace GMockUtils {
// Call once per test class or module to set up everything needed by GoogleMock.
void InitGoogleMock();
// Call once per test method to check for GoogleMock messages.
void CheckGoogleMock();
}
}
GMockUtils.cpp
#include "stdafx.h"
#include "GMockUtils.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace testing {
namespace GMockUtils {
namespace {
// Test event listener for use with CppUnitTestFramework
class CppUnitTestReporter : public EmptyTestEventListener
{
public:
CppUnitTestReporter() : _failed(false)
{
}
// Helper for converting std::string to std::wstring
std::wstring to_wstring(const std::string& str) const
{
std::wstring output;
std::copy(str.begin(), str.end(), std::back_inserter(output));
return output;
}
// Called after a failed assertion or a SUCCEED() invocation.
void OnTestPartResult(const ::testing::TestPartResult& result) override
{
// Log this result to the CppUnitTestFramework output
Logger::WriteMessage(result.summary());
// Note: You cannot do an Assert directly from a listener, so we
// just store the messages until CheckGoogleMock() is called.
if (result.failed())
{
_failed = true;
// Append this result to the running summary
_failedSummary += result.message();
_failedSummary += "\n";
}
}
// Clear any previous failures
void ResetFailures()
{
_failed = false;
_failedSummary.clear();
}
// Assert if any failures have been detected. Also resets failures.
void CheckFailures()
{
auto failed = _failed;
auto failedSummary = _failedSummary;
ResetFailures();
Assert::IsFalse(failed, to_wstring(failedSummary).c_str());
}
protected:
bool _failed;
std::string _failedSummary;
} *_listener;
}
// Initialize the Google Mock framework for use with CppUnitTestFramework
void InitGoogleMock()
{
// Avoids calling the function unnecessarily
if (_listener != nullptr)
return;
// Dummy command line parameters (could pass exe path here)
int argc = 0;
char** argv = nullptr;
// Initialize the framework
::testing::InitGoogleMock(&argc, argv);
// We don't want exceptions thrown, regardless what the doc says
GTEST_FLAG(throw_on_failure) = false;
// Remove default listener
auto &listeners = UnitTest::GetInstance()->listeners();
delete listeners.Release(listeners.default_result_printer());
// Create and install the new listener
_listener = new CppUnitTestReporter();
listeners.Append(_listener);
}
// Reset any previous failures detected by the listener
void ResetGoogleMock()
{
_listener->ResetFailures();
}
// Prints messages and asserts if any Google Mock messages are found.
void CheckGoogleMock()
{
Assert::IsNotNull(_listener, L"Google Mock framework not initialized by InitGoogleMock()");
_listener->CheckFailures();
}
}
}
I use the GMockUtils functions in unit test classes like this:
#include "GMockUtils.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ::testing;
namespace GMockUtilsDemo
{
TEST_CLASS(GMockUtilTests)
{
public:
TEST_CLASS_INITIALIZE(ClassInitializer)
{
// IMPORTANT: This must be called before any mock object constructors
GMockUtils::InitGoogleMock();
}
TEST_METHOD_CLEANUP(MethodCleanup)
{
// Checks for GoogleMock messages. Asserts if found.
GMockUtils::CheckGoogleMock();
}
TEST_METHOD(Method1_ParamIsOne_Method2CalledWithOne)
{
MockTestClass mockObj;
EXPECT_CALL(mockObj, Method2(1)).Times(1); // Expectation will be met
mockObj.Method1(1);
}
TEST_METHOD(Method1_ParamIsZero_IntentionallyFail)
{
MockTestClass mockObj;
EXPECT_CALL(mockObj, Method2(1)).Times(1); // Expectation will not be met
mockObj.Method1(0);
}
};
}
The Console Output
The console output now shows all GMock messages, and the run does not abort on the first test failure.
[3/27/2019 12:23:46 PM Informational] ------ Run test started ------
[3/27/2019 12:23:46 PM Informational]
Unexpected mock function call - returning directly.
Function call: Method2(0)
Google Mock tried the following 1 expectation, but it didn't match:
c:\...\gmockutilsdemo.cpp(64): EXPECT_CALL(_mockObj, Method2(1))...
Expected arg #0: is equal to 1
Actual: 0
Expected: to be called once
Actual: never called - unsatisfied and active
[3/27/2019 12:23:46 PM Informational] Actual function call count doesn't match EXPECT_CALL(_mockObj, Method2(1))...
Expected: to be called once
Actual: never called - unsatisfied and active
[3/27/2019 12:23:46 PM Informational] ========== Run test finished: 2 run (0:00:00.8631468) ==========
Test Explorer View
If I run the tests via Visual Studio Test Explorer, I can also see all GMock messages related to a particular test. It also works with the VsTest task on Azure DevOps.
Hopefully this will be useful to anyone who finds themselves in the same situation.
I am writing unit test case for my internal method. I have made necessary changes in AssemblyInfo.cs of my mail class project
[assembly: InternalsVisibleTo("myunitest_assemblyname")]
now i can access my internal method in unit test case method.
but when i compile the code it is giving an error as below
Error 1 'main class project name' does not contain a definition for 'Process' and no extension method 'Process' accepting a first argument of type 'main class project name' could be found (are you missing a using directive or an assembly reference?)
my main class has strong name.
it would be great if some one point where i am missing.
main class structure
namespace Renewals
{
public class StateProcessor
{
internal virtual void PutEmailInQueue(DataTable dataTable)
{
}
}
}
//test class structure
namespace Renewals.Tests.Unit
{
[TestClass]
public class StateProcessorTest
{
[TestMethod]
public void PutEmailInQueueTest()
{
DateTime processingDate = Convert.ToDateTime("27-feb-2013"); ;
StateProcessor stateProcess = new StateProcessor(processingDate);
stateProcess.PutEmailInQueue(new DataTable());
}
}
}
PutEmailInQueue - this method giving me problem.
you wrote that your class use strong name.
I think you have to modify your InternalsVisibleTo() statement with the public key.
e.g.: [assembly: InternalsVisibleTo("friend_signed_B, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e3aedce99b7e10823920206f8e46cd5558b4ec7345bd1a5b201ffe71660625dcb8f9a08687d881c8f65a0dcf042f81475d2e88f3e3e273c8311ee40f952db306c02fbfc5d8bc6ee1e924e6ec8fe8c01932e0648a0d3e5695134af3bb7fab370d3012d083fa6b83179dd3d031053f72fc1f7da8459140b0af5afc4d2804deccb6")]
for more informations see: http://msdn.microsoft.com/en-us/library/bb385180.aspx
I try to use MSTest so as to perform unit tests on native C++ code (so as to try to implement Test Driven Development).
There's an MSTest entry in the "Add New Project" C++ Wizard. It creates some code obviously in C+++/CLI.
However, whenever I try to run these tests, Visual Studio indicates me that the tests are not runnable:
Not Runnable TestMethod2 CargoOCRTests UTA007: Method TestMethod2 defined in class CargoOCRTests.UnitTest1 does not have correct signature. Test method marked with the [TestMethod] attribute must be non-static, public, does not return a value and should not take any parameter. for example: public void Test.Class1.Test().
However I think my two tests functions do respect the prototype VS is complaining about:
namespace CargoOCRTests
{
[TestClass]
public ref class UnitTest1
{
[TestMethod]
void TestMethod1()
{
Assert::IsTrue(true);
};
[TestMethod]
void TestMethod2()
{
Assert::IsTrue(false);
};
};
}
Have you any idea what is the cause ?
You need to mark your test methods as public
public:
[TestMethod]
void TestMethod1() {}