Jump to content
  • Advertisement
  • entries
    34
  • comments
    31
  • views
    5914

C++ Set Up GMock for TDD. C++, VS

8Observer8

1282 views

If you need the example how to set up GTest without GMock you can see this example: Set Up GTest for TDD. C++, VS

In this example: PersonService_GMockCpp.zip  we will see how to use Google Mock for creating mock objects and how to write a unit test for testing exceptions. I translated this example from the TypeScript tutorial: Using Jasmine Spies to Create Mocks and Simplify the Scope of Your Tests

You can download and run the example. Google Test library is included in the project as source folder and it is placed in "Libs" folder.

Note. If you have another version of VS then before you will run unit tests you need to select VS 2017, like in this screenshot:

Spoiler

PlatformToolset.png.3c9a59798e0e30baeee97b337b6bbe48.png

You need to:

  • open the solution. The solution is file with name: "PersonService.sln"
  • select your version of VS, for example VS 2017 instead of VS 2015 as in the screenshot above
  • make the "PersonService.UnitTests" project as "StartUp Project". For this: make right mouse button click on the "PersonService.UnitTests" project -> select "Set as StartUp Project"
  • press Ctrl+F5 to run unit tests

How to set up GTest and GMock from scratch

I use version 1.8.1 of GTest and GMock. You can download these libraries here:

You need to create a new solution. Write some name for you solution and for your project, for example: PersonService (for the solution and for the project). Pay attention, you need to check "Create directory for solution" when you create a new solution and project.

Note. RMB - Right Mouse Button click.

You can set up the project from scratch like this:

  • Create a new solution with the name "PersonService". Check "Create directory for solution". Write name "PersonService" for project. Set a new project as: empty console project, without the "precompiled headers". The "PersonService" project will be a project under test
  • Copy and add these files to the "PersonService":

IDataContext.h

#pragma once

#include "Person.h"

class IDataContext
{
public:
    virtual ~IDataContext() {};
    virtual void SavePerson(const Person &person) = 0;
};

IPersonValidator.h

#pragma once

#include "Person.h"

class IPersonValidator
{
public:
    virtual ~IPersonValidator() {};
    virtual bool IsValid(const Person &person) = 0;
};

Person.h

#pragma once

#include <string>

class Person
{
public:
    int number;
    std::string name;
};

PersonService.h

#pragma once

#include "Person.h"
#include "IPersonValidator.h"
#include "IDataContext.h"

class PersonService
{
public:
    PersonService(IPersonValidator *validator, IDataContext *dataContext);

    void Save(const Person &person);

private:
    IPersonValidator *_validator;
    IDataContext *_dataContext;
};

PersonService.cpp

#include "PersonService.h"

PersonService::PersonService(IPersonValidator *validator, IDataContext *dataContext)
{
    _validator = validator;
    _dataContext = dataContext;
}

void PersonService::Save(const Person &person)
{
    if (_validator->IsValid(person))
    {
        _dataContext->SavePerson(person);
    }
    else
    {
        throw std::runtime_error("Person is not valid");
    }
}
  • Add a new project in your solution. For this: RMB on the solution name -> "Add" -> "New Project..." -> Set a name: "PersonService.UnitTests". You project must be: console, empty and without the "precompiled headers". The "PersonService.UnitTests" project will have unit tests for the "PersonService" project
  • Create the "Libs" folder in your solution folder (where your ".sln" file is placed)
  • Copy the "gtest-1.8.1" and the "gmock-1.8.1" folders to the "Libs" folder from these archives: gtest-1.8.1.zipgmock-1.8.1.zip
  • Open the project properties of the project "PersonService.UnitTests" (RMB on the project name and select "Properties") and add these lines to "C/C++" -> "General" -> "Additional Include Directories":
$(SolutionDir)Libs\gtest-1.8.1\include
$(SolutionDir)Libs\gtest-1.8.1
$(SolutionDir)Libs\gmock-1.8.1\include
$(SolutionDir)Libs\gmock-1.8.1
$(SolutionDir)PersonService
  • Click "Apply" and "OK" buttons
  • Make "PersonService.UnitTests" as "StartUp Project". For this: RMB on the "PersonService.UnitTests" project -> select "Set as StartUp Project"
  • Add as "Existing Item" this file: "Libs\gtest-1.8.1\src\gtest-all.cc" and "Libs\gmock-1.8.1\src\gmock-all.cc". For this: RMB on the "PersonService.UnitTests" project -> select "Add" -> "Existing Item..." -> choose these files: "Libs\gtest-1.8.1\src\gtest-all.cc" and "Libs\gmock-1.8.1\src\gmock-all.cc"
  • Add as "Existing Item" the files that you will test. For example, in this case: "PersonService.cpp" from the "PersonService" project
  • Copy and add these files to the "PersonService.UnitTests":

main.cpp

#include <gmock/gmock.h>
#include <gtest/gtest.h>

int main(int argc, char **argv)
{
    testing::InitGoogleMock(&argc, argv);
    return RUN_ALL_TESTS();
}

PersonServiceTests.cpp

#include <gmock/gmock.h>
#include <gtest/gtest.h>

using ::testing::_;
using ::testing::Return;

#include "IDataContext.h"
#include "IPersonValidator.h"
#include "Person.h"
#include "PersonService.h"

class MockDataContext : public IDataContext
{
public:
    MOCK_METHOD1(SavePerson, void(const Person &person));
};

class MockPersonValidator : public IPersonValidator
{
public:
    MOCK_METHOD1(IsValid, bool(const Person &person));
};

TEST(PersonService, IsValid_ValidPerson_CallSavePerson)
{
    MockDataContext dataContext;
    MockPersonValidator validator;
    PersonService service = PersonService(&validator, &dataContext);
    Person validPerson;

    EXPECT_CALL(validator, IsValid(_))
        .WillOnce(Return(true));

    EXPECT_CALL(dataContext, SavePerson(_)).Times(1);

    service.Save(validPerson);
}

TEST(PersonService, IsValid_NotValidPerson_ThrowException)
{
    MockDataContext dataContext;
    MockPersonValidator validator;
    PersonService service = PersonService(&validator, &dataContext);
    Person validPerson;

    EXPECT_CALL(validator, IsValid(_))
        .WillOnce(Return(false));
    EXPECT_CALL(dataContext, SavePerson(_)).Times(0);

    //EXPECT_THROW({
    //    service.Save(validPerson);
    //}, std::runtime_error);

    try
    {
        service.Save(validPerson);
        FAIL() << "Exptected std::runtime_error";
    }
    catch (std::runtime_error const & err)
    {
        EXPECT_EQ(err.what(), std::string("Person is not valid"));
    }
    catch (...)
    {
        FAIL() << "Exptected std::runtime_error";
    }
}
  • Run the "PersonService.UnitTests" project by pressing on "Ctrl+F5" buttons
  • You will see that you tests passed:

PersonService_GMockCpp.png.9a906ca66fe6f016361ce2635579ff39.png



0 Comments


Recommended Comments

There are no comments to display.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Advertisement
  • Blog Entries

  • Similar Content

    • By RamblingBaba
      Hello, so I thought I would find information on this really easy. Surprisingly, I could not find anything of value. Perhaps I'm searching for the wrong thing, I'm not great a math and it has been a while.
      I wanted to create a line (arrow), set attributes (angle, mass, velocity, etc) and have it shoot off in the air. Much like the old school game Gorillas if anyone has played that. I tried looking up Archery formulas, Bow and Arrow formulas. Arrow mathematics. But mostly found stuff about the paradox path. The best I found was KE = 1/2MV. Which seemed like part of something I would need.
      Can someone perhaps break this down into separate components, or if possible link me to a good article or simple source code (even just console and plugging values)? I'm using SFML btw, How could I grab the correct angle as it is in flight so that it comes down "realistically". 
       
      PS: I'm sure you have seen flash games where you set the power and angle and let the arrow fly with various targets of different points. Maybe worms is a better example. 
      Thanks
       
    • By Trexioas Xavier
      I am having difficulties trying to understand how a fragment shader (GLSL) works in OpenGL. To be more specific, how does OpenGL reads the color/texture data?
      In the vertex Shader (GLSL) there is a pre-defined variable that sets the vertex data called gl_Position.
      So basically I am asking, what is the variable/method that sends color/texture data to the OpenGL program in the fragment shader or do i just type
      out vec4 fragColor;
      does that work? (above code)
    • By Harry Loretz
      Hello everyone, I really appreciate all the help i can get. I am starting to become quite well developed as a C++ programmer within the unreal engine, i am still learning though. I am looking to find some example code, and some information on how player controllers should be written in C++ within the Unreal engine with the current version of 4.23.1 too. I understand that player controllers can control inputs for a character or pawn, but i don't understand how to set this up. My real question is what Code is needed for the most bare basic C++ Player controller that functions for a character? Please help.

      Thankyou for reading.
    • By Alio
      gdb says I.m getting a segfault in InputHandler::update when I mive the joystick, is it that the if else and for loops in the function are not seperated correctly, where do I need to add or remove french braces? I'm a complete noob and I find nested if else and for loops really hard to debug so any help is greatly appreciated. Thanks
      InputHandler.cpp and all the other game engine files are included here
      https://drive.google.com/open?id=1o6nLpkkKs9aafBMv1Q3AXYEmX0a_YkAX
    • By AnakinDev
      I decided to upgrade my source file from vs2003 to vs2017 which uses direct X as game engine. After compiling all the solution I encountered these problems. It says the library errors are ggsrvlib26_MT.lib, lua.lib, d3dx9dt.lib, dxerr9.lib, N4GamesLib4.lib.

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!