How to mock non virtual methods?
Moq cannot mock non virtual methods on classes. Either use other mocking frameworks such as Type mock Isolator which actually weaves IL into your assembly or place an interface on EmailService
and mock that.
Mock non-virtual method C++ (gmock)
It means you will have to templatize your production code. Using your example:
CSumWind
class definition:
class CSumWnd : public CBaseWnd
{
private:
bool MethodA()
};
Mocked CSumWnd
class definition:
class MockCSumWnd : public CBaseWnd
{
private:
MOCK_METHOD(MethodA, bool());
};
Production class which have to be tested with mocked class CSumWind
. Now it becomes templated to provide using CSumWind
class in production code and MockCSumWnd
class in tests.
template <class CSumWndClass>
class TestedClass {
//...
void useSumWnd(const CSumWndClass &a);
private:
CSumWndClass sumWnd;
};
Instantiation of TestedClass
in production:
TestedClass <CSumWnd> obj;
Instantiation of TestedClass
object in test executable:
TestedClass <MockCSumWnd> testObj;
How to mock Non-virtual Methods in concrete classes using gmock?
Define dependencies(The random generator here) as local variables are not recommended, it's much harder to do dependencies injection(Or it won't be possible), so I change the functions Rng_t
into template function and pass the Rng as a parameter.
In practice to construct a random generation may be heavy work, it needs to initialize its internal status, to construct it every time we call the function flipCoin
is waste.
The non-virtual function can be mocked, one most commonly used strategy is to use the template, here we make the class CoinFlipper's member function as a template function, then we can test the dependency with our MockRng
.
Be aware that for the template function, we need to define the member function in the header file.
coinflipper.h:
#pragma once
#include "rng.h"
class CoinFlipper {
public:
enum Result { HEADS = 0, TAILS = 1 };
template <typename Rng_t>
Result flipCoin(Rng_t& rng) {
const double val = rng.generate(0.0, 1.0);
return (val < 0.5) ? HEADS : TAILS;
}
};
The test file part, MockRng
doesn't inherit anything now. And the test member function we use here has the type CoinFlipper::flipCoin<MockRng>
. For production code: we use the type CoinFlipper::flipCoin<Rng>
//#include "mockrng.h"
#include "coinflipper.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class MockRng {
public:
MOCK_METHOD2(generate, double(double, double));
};
TEST(CoinFlipper, ShouldReturnHeadsIfRandValueIsLessThanProbability) {
MockRng rng;
EXPECT_CALL(rng, generate(::testing::DoubleEq(0.0), ::testing::DoubleEq(1.0)))
.Times(::testing::Exactly(1))
.WillOnce(::testing::Return(0.25));
CoinFlipper coinFlipper;
auto result = coinFlipper.flipCoin<MockRng>(rng);
EXPECT_EQ(CoinFlipper::HEADS, result);
}
See related question here:
Mock non-virtual method C++ (gmock)
The official document:
https://chromium.googlesource.com/external/github.com/google/googletest/+/refs/tags/release-1.8.0/googlemock/docs/CookBook.md
Verify non-virtual method with Moq
You can only mock (or verify) a method if you are mocking an interface, or if it's a concrete class and the method is virtual.
Does DoSomething() rely on any dependencies? If not, you could just unit test your class without Moq. If it does, you could mock those dependencies and verify there.
Mocking non virtual posted model properties and method
Am I doing something wrong
This appears to be an XY problem.
is there any way to do it without changing the implementation code
There really is no need for moq in this scenario. You can use inheritance to craft a fake model to be used in the test. The fake model will override the method that is tightly coupled to the database. (more on that later)
public class FakePerson : PersonModel {
public new string Get() {
return string.Empty; //Not calling the base Get
}
}
The test can then be refactored to use the fake model and be exercised to completion as intended.
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown() {
//Arrange
var fakePersonModel = new FakePerson() {
Name = string.Empty,
SelectionSubmitted = true
};
var controller = new HomeController();
//Act
controller.Index(fakePersonModel);
//Assert
var isShowSummarySetToTrue = fakePersonModel.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
That aside, your model appears to be doing to much if the actual Get
implementation does as you stated here
actual implementation return some value from the db
Consider refactoring that functionality out into a service (Single Responsibility Principle / Separation of Concerns)
public interface IPersonModelService {
string Get(PersonModel person);
}
public class PersonModelService : IPersonModelService {
public string Get(PersonModel person) {
//actual implementation return some value from the db
}
}
and keep the model as lean as possible. Also consider refactoring those public fields into public properties.
public class PersonModel {
public bool SelectionSubmitted { get; set; }
public bool ShowValidationSummary { get; set; }
public string Name { get; set; }
}
The controller would depend on the service abstraction
class HomeController : Controller {
private IPersonModelService service;
public HomeController(IPersonModelService service) {
this.service = service;
}
[HttpGet]
public ActionResult Index(PersonModel model) {
if (model.SelectionSubmitted && !ValidateSelections(model)) {
model.ShowValidationSummary = true;
}
return View("Index", service.Get(model));
}
private bool ValidateSelections(PersonModel model) {
if (model.Name == "") {
ModelState.AddModelError("EmptyPersonName", "Person name cannot be null");
}
return ModelState.IsValid;
}
}
And now the test can be exercised to completion in isolation.
[TestMethod]
public void GivenPerson_WhenSearchingForFutureBirthDate_ThenValidationMessageShouldBeShown() {
//Arrange
var model = new PersonModel() {
Name = string.Empty,
SelectionSubmitted = true
};
var serviceMock = new Mock<IPersonModelService>();
serviceMock.Setup(_ => _.Get(It.IsAny<PersonModel>())).Returns(string.Empty);
var controller = new HomeController(serviceMock.Object);
//Act
controller.Index(model);
//Assert
var isShowSummarySetToTrue = model.ShowValidationSummary;
Assert.IsTrue(isShowSummarySetToTrue);
}
Mocking non-virtual methods in C++ without editing production code?
I would write a Perl/Ruby/Python script to read in the original source tree and write out a mocked source tree in a different directory. You don't have to fully parse C++ in order to replace a function definition.
Mocking class with no virtual methods
There may be a way, but it's not as nice as the simple way of overriding a virtual function.
First, if the function is not virtual and is inline, you're likely out of luck. When the compiler saw a call to obj.Add()
or ptr->Add()
, the fact the function is not virtual means it didn't need to worry about the possibility some function other than Test::Add()
might need to be the one actually called. So it most likely either directly inlined the code from the definition of Add
, in which case replacing it is near impossible, or it put a weakly-linked copy of the Test::Add()
into the same object file as the function calling it. In that second case, you might be able to replace it using linker tricks, depending on the platform you're using - until later the compiler switches to deciding to inline it after all.
If it's just the class Test
you don't want to modify, but you're okay with changing the code that uses Test
as a dependency and will be tested by the unit test, you could do template dependency injection. But the question sounds like you probably don't want to modify that code either.
Now assuming the function is not inline, and is defined in some file "Test.cpp", and the class is polymorphic (which it is in the example because of the virtual destructor) you can replace all the definitions from that file, to make them act as though they were virtual even if they're not:
Write the Google Mock class as usual, with the functions you want to be able to detect mocked.
#include "Test.hpp"
#include <gmock/gmock.h>
class MockTest : public Test
{
public:
MOCK_METHOD0(Add, int());
MOCK_CONST_METHOD0(Print, void());
};
(I've added a const method to the example, to show how to deal with them also.)
In the same unit test code, write definitions for the mocked functions like this.
int Test::Add()
{
if (auto* mock = dynamic_cast<MockTest*>(this))
return mock->Add();
// Next comes what to do if the code ever calls Add on
// a Test which is not actually a MockTest. This could
// be a stub implementation, an actual implementation, or
// could intentionally terminate, throw, or note a gtest error.
ADD_FAILURE() << "Test is not a MockTest";
return 0;
}
void Test::Print() const
{
if (auto* mock = dynamic_cast<const MockTest*>(this)) {
mock->Print();
return;
}
ADD_FAILURE() << "Test is not a MockTest";
}
You may also need to write at least stubs for other definitions in the Test.cpp file to make the linker happy. This doesn't necessarily mean they would actually get called or otherwise used.
- When linking the unit test, make sure the real Test.cpp file is NOT provided. If it's normally part of a library, you may need to list out the other files from that library on the command line. This might lead to dependency order issues and/or circular dependency issues. GNU's linker has "-Wl,--start-group ... -Wl,--end-group" to deal circular link issues by repeatedly trying some objects and/or libraries in a loop until as much as possible has been resolved; I'm not sure about other systems.
Related Topics
How to Compare Two Rich Text Box Contents and Highlight the Characters That Are Changed
Escape Special Character in Regex
Is There a Good Way to Convert Between Bitmapsource and Bitmap
Difference Between Parameters.Add(String, Object) and Parameters.Addwithvalue
System.Text.JSON API Is There Something Like Icontractresolver
Editing Dictionary Values in a Foreach Loop
How to Validate Azure Ad Security Token
How to Call a Vbscript File in a C# Application
String = String + Int: What's Behind the Scenes
Executing Ssis 2012 Package That Has Script Components from External Application
How Enumerate All Classes with Custom Class Attribute
How to Hide Tabpage from Tabcontrol