How to Mock Non Virtual Methods

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:

  1. 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.)


  1. 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.


  1. 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



Leave a reply



Submit