Let’s say I’m writing a car class. It should have the methods configEngine and currentGasolineConsumption beside some other methods. So I refactored out the calculation of the gasoline consumption into an Engine class and use polymorphism to get the current gasoline consumption:
class AbstractEngine()
{
public:
virtual int calculateGasolineConsumption()
{
//... do calculation ...
return consumption;
}
// some other (pure virtual) methodes
};
class EngineA() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
};
class EngineB() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
};
class EngineC() : public AbstractEngine
{
public:
// implementation of the pure virtual methodes
int calculateGasolineConsumption() override
{
//... do new calculation ...
return consumption;
}
};
enum EngineType {
ENGINE_A,
ENGINE_B,
ENGINE_C,
};
void configEngine(EngineType engineType)
{
m_engine = m_engineFactory.create(engineType);
}
int currentGasolineConsumption()
{
return m_engine.calculateGasolineConsumption();
}
Now my question is how to unittest this without getting duplication in my unit tests?
If I write three unittests, for configEngine(ENGINE_A) and configEngine(ENGINE_B) would test basically the same code of the abstract superclass and I don’t like that duplication.
struct EngineSpec {
EngineType engineType;
int expectedValue;
};
INSTANTIATE_TEST_CASE_P(, tst_car, ::testing::Values(
EngineSpec { ENGINE_A, 3 },
EngineSpec { ENGINE_B, 3 },
EngineSpec { ENGINE_C, 7 }
));
TEST_F(tst_car,
currentGasolineConsumption_configWithEngine_expectedBehaviour)
{
EngineSpec engineSpec = GetParam();
//Arrange
m_car.configEngine(engineSpec.engineType);
//Act
auto result = m_car.currentGasolineConsumption();
//Assert
EXPECT_EQ(engineSpec.expectedValue, result);
}
Of course there is only one duplicate/unnecessary unittest but this is only a minimal example. In my real code the number of unit test duplication would explode.
One additional thing: I don’t want to move the Engine class outside of the ‘module’ and use dependency injection because I think this ‘internal Engine class’ approach is easier to handle for the client. So the client has only one interface and some enums to use this module. I would like to treat the Engine class as implementation detail.
Ideally tests should know as little about the implementation as possible, because 10 years down the line when the abstraction doesn't quite work any more, or is part of a large complicated inheritance chain (e.g. what happens when you get a hybrid engine?) the tests that appear to be a lot of effort right now will still work perfectly.
However, if you want to be pragmatic and don't mind coupling your tests to the implementation a little, you could extract a testGasolineConsumption(AbstractEngine engine) method that is called from a test case for each child. This would check that the implementation works correctly and that the base class behaviour hasn't been overridden.
Related
I am a beginner with google testing framework and have looked up for the solution to this question on SO, but could not find any solutions with respect to C++. Anyway here is what i am trying to do. I have a state machine(service) which is called inside a client code.
//IStateMachine.h
class IStateMachine
{
public:
bool Run(const std::string& action) = 0;
bool IsTxnValid(const std::string& action)= 0;
}
//StateMachine.h
class StateMachine : public IStateMachine
{
bool Run(const std::string& action) override;
bool IsTxnValid(const std::string& action) override;
}
//StateMachine.cpp
bool StateMachine::IsTxnValid(const std::string& action)
{
//Checks whether the given action is valid for the given state.
}
bool StateMachine::Run(const std::string& action)
{
if(IsTxnValid(action)) // #E
{
//Do processing
return true;
}
return false;
}
//Client.h contains a class Client which has function called RunService.
Client
{
public:
void RunService();
std::unique_ptr<IStateMachine> service_; // Initialised to a non null value in either ctr or
// factory.
}
//Client.cpp
bool Client::RunService(std::string&action)
{
if(!service_->Run(action)) //Run in turn calls IsTxnValid().
{
return false;
}
return true;
}
Now i am writing a test case to test the functioning of RunService. I am expecting that if Client::IsTxnValid(param) returns false, then so should RunService.
I have successfully set up the testing recipe and could get the basic tests running. Here is the relevant test i have written. On running this test the i get the error, that IsTransitionValid is never called.
TEST_F(ClientTest, RunService)
{
EXPECT_CALL(*p_service, Run("some_action")); // #A
// EXPECT_CALL(*p_service, Run(testing::_)).WillOnce(::testing::Return(true)); //#B
EXPECT_CALL(*p_service,IsTransitionValid(testing::_)).WillOnce(::testing::Return(false)); //#C : This never gets called.
EXPECT_EQ(false, x_client->RunService());
}
How do i correctly call IsTransitionValid ?
You don't need to set this expectation. I'd go even further: you should not even depend on the implementation of Run in IStateMachine: you should only care about what input it is provided with (parameters, checked with matchers) and what output it can return (so basically only the contract between these two classes) and that's the beauty of it!
It is an implementation detail of StateMachine class (the real implementation) what is done when Run is called. The only thing you need to check in your test is to act upon the result of Run. Using triple A rule (arrange, act, assert): you arrange the test case conditions (using EXPECT_CALLs), then you act (calling RunService) and then you assert (checking the result of RunService).
The technical details:
When you create a mock by inheriting from class Foo:
class Foo {
public:
virtual ~Foo() = default;
virtual void bar() = 0;
}
By defining:
class FooMock : public Foo {
MOCK_METHOD0( bar, void());
}
gmock will add bar (the method to override) and gmock_bar (internal detail of gmock) methods to FooMock class. bar has empty implementation in this case. FooImpl and FooMock share the interface, but have different implementations - hence no call to IsTxnValid is made in Run: the mock class just doesn't know (nor care) how Run is implemented in StateMachine. Remember: in your testcase you interact with StateMachineMock and you only care about the interaction with its public interface, the contract between these two classes and how they cooperate together.
That being said, you of course need to utest the StateMachine class. It may depend on yet another interfaces in its implementations: that will be tested with different set of mocks. But Client should not know about this.
I'm attempting to write Mocks for Private / Non Virtual / Static functions and come across a way to do the same.
Here is how it looks like..
Lets assume that I have a class A which needs to be mocked and used inside class UsingA. The definition of both classes looks like
class A
{
friend class UsingA;
int privateFn() {}
public:
int nonVirtual() {}
};
// The UsingA class
class UsingA {
A &a1;
public:
UsingA(A & _a1) : a1(_a1) {}
int CallFn() {
return a1.nonVirtual();
}
int CallFn2() {
return a1.privateFn();
}
};
I know that Mocks are meant for generating the behavior of the class and while creating Mocks, we need to derive from the original class.
However, to Mock the behavior I decided not to derive from the original class, instead comment the class A and generate a Mock class with the same Name i.e class A.
Here is how my mock class looks like
// Original class A is commented / header file removed
class A {
public:
MOCK_METHOD0(nonVirtual, int());
MOCK_METHOD0(privateFn, int());
};
And my tests are usual mock tests
TEST(MyMockTest, NonVirtualTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, nonVirtual())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn();
EXPECT_EQ(retVal,100);
}
TEST(MyMockTest, PrivateTest) {
A mstat;
UsingA ua(mstat);
EXPECT_CALL(mstat, privateFn())
.Times(1)
.WillOnce(Return(100));
int retVal = ua.CallFn2();
EXPECT_EQ(retVal,100);
}
And everything works fine and I'm able to test UsingA by this mock.
Question is.
This looks easier and serves the purpose, still I haven't seen this kind of examples while browsing for google mock examples. Is there anything that would go wrong if I do this?
Honestly, I didn't find any.
NOTE: Folks, I'm using friend for demonstration only. My actual use case is totally different. Thanks
The wrong is that you are not testing real code, because of that:
comment the class A
generate a Mock class with the same name
These operations alter the code under test.
An example what can go wrong:
Change return type: long nonVirtual in Mock - previously was int
Test that on, let say, nonVirtual() == 0xFF'FFFF'FFFF (which is bigger than INTMAX) some action is being done
Forget to change in real A - so real UsingA have branch that is tested but never reachable in real code
An example code:
class A {
public:
MOCK_METHOD0(nonVirtual, long()); // change
MOCK_METHOD0(privateFn, int());
};
void UsingA::processA()
{
if (a.nonVirtual() > VERY_BIG_NUMBER)
{
throw runtime_error("oops");
}
}
TEST_F(UsingATest, throwOnVeryBigNumber)
{
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VERY_BIG_NUMBER + 1));
ASSERT_THROW(objectUndertTest.processA());
}
But real A did not change - so we test non reachable code in UsingA class:
class A {
public:
int nonVirtual(); // not changed
...
};
The best solution is (in order):
To test in isolation you have to isolate classes - so to use dependency injection (virtual functions etc, base interfaces, etc...) - this is sometimes called London School of TDD
Test both classes A and UsingA w/o any stubbing - test them together in one testcase - thus you test real code - this is called Detroit Shool of TDD
Separate by template code with good restriction on interface - this approach is most similar to yours:
Regarding 3 - you might use something like this:
template <class T = A>
class UsingA {
T &a1;
public:
UsingA(T & _a1) : a1(_a1) {}
long CallFn() {
using ANonVirtualResult = std::invoke_result_t<&T::nonVirtual>;
static_assert(std::is_same<long, ANonVirtualResult>::value);
return a1.nonVirtual();
}
...
};
And in test:
class UsingATest : public ::testing::Test
{
protected:
StrictMock<AMock> aMock;
using ClassUnderTest = UsingA<AMock>;
ClassUnderTest objectUnderTest{aMock};
};
TEST_F(UsingATest, useNonVirtual)
{
const auto VALUE = 123456;
EXPECT_CALL(aMock, nonVirtual()).WillOnce(Return(VALUE));
ASSERT_EQ(VALUE, objectUnderTest.CallFn());
}
You might note that some assumption about A might be tested during compilation as static_assert or via some SFINAE technics (more complicated).
Actually, there are examples with template code in googlemock as workaround for mocking classes w/o virtual functions.
We use your type of using mocks inside a few of our test projects to check callbacks on a larger class that we pass along using dependency injection. In our case, the methods are declared virtual.
In your case, they are not. Your mock implementation would hide the original implementation - if there was any. So I don't think there's an issue here.
Hi I am using test driven development and seem to be in an area I am not familiar. Could you Please check and let me know what changes I should make in my code to make it "unit testable" ?
Code to be tested:
public void PurchaseItemList()
{
//call methods to checkavailablility
If(!productAvailable)
{
purchaseItemEventArgs.IsSuccessfull = false;
}
else
{
purchaseItemEventArgs.IsSuccessfull = true;
// code to update model.
purchaseItemEventArgs.ItemsPurchased = GetItemsPurchased()
}
}
Now the issue I face is that I cannot mock the purchaseItemEventArgs class as it does not implement any interface. I am using moq for testing. Any advise on the code changes to make it unit testable would be very helpfull.
Thanks
Since GetItemsPurchased() is a method of your class, you could make it protected virtual. So you could then define a test class like this:
class TestableMyClass : MyClass{
private Items _items;
public TestableMyClass(Items items) : base() {
_items = items;
}
protected Items GetItemsPurchased(){
return _items;
}
}
And then, in your tests, replace new MyClass by new TestableMyClass(myItems).
This way, your actual GetItemsPurchased() won't be called in your tests, and you can inject the items you want.
I want to test makeTvSeries() method without extracting getNumberOfShows, printMsg to other class and then mocking it so I thougth about mocking TvChannel class.
Is it possible to call base class method (makeTvSeries) which will call child methods: getNumberOfShows, printMsg without getting rid of virtuality? So I could use same mock class definiton in other tests for instance foo.playTvSeries(mockTvChannel) and expect calls to makeTvSeries?.
Moreover is it good practice what I am doing at all? In whole program there are also other classes which use cin and cout and as I said at the begining I didn't wanted to extract all of them to one class responsible for input/output. What are Yours experiences and what I should do ?
class MockTvChannel : public TvChannel{
public:
MOCK_METHOD0(getNumberOfShows, int());
//MOCK_METHOD0(makeTvSeries, void());
MOCK_METHOD0(printMsg, void());
};
TEST(sample_test_case, sample_test)
{
MockTvChannel channel;
EXPECT_CALL(channel, getNumberOfShows())
.Times(1)
.WillOnce(::testing::Return(10));
EXPECT_CALL(channel, printMsg())
.Times(10);
channel.makeTvSeries();
}
class TvChannel
{
protected:
virtual int getNumberOfShows(){
int nShows;
std::cin >> nShows;
return nShows;
}
virtual void printMsg(){
std::cout << "What a show!" << std::endl;
}
public:
/*virtual*/ void makeTvSeries()
{
int nShows = getNumberOfShows();
for(int i = 0; i<nShows; ++i){
printMsg();
}
}
virtual ~TvChannel() {};
};
So I could use same mock class definiton in other tests for instance foo.playTvSeries(mockTvChannel) and expect calls to makeTvSeries?
Yes, you can. And your implementation is fine.
is it good practice what I am doing at all?
It is. Following the SOLID principle, you applied next principles :
LSP : in unit test you switched real implementation and tested using mock, so your makeTvSerier works
ISP : your class has an interface
DIP : I guess, you want to use inversion of control when you pass instance of mock to other objects
I'm trying to start using Unit Testing on my current project in Visual Studio 2010. My class structure, however, contains a number of interface and abstract class inheritance relationships.
If two classes are derived from the same abstract class, or interface I'd like to be able to share the testing code between them. I'm not sure how to do this exactly. I'm thinking I create a test class for each interface I want to test, but I'm not sure the correct way to feed my concrete classes into the applicable unit tests.
Update
OK here's an example. Say I have an interface IEmployee , which is implemented by an abstract class Employee, which is then inherited by the two concrete classes Worker and Employee. (Code show below)
Now say I want to create tests that apply to all IEmployees or Employees. Or alternatively create specific tests for specific types of Employees. For example I may want to assert that setting IEmployee.Number to a number less then zero for any implementation of IEmployee throws an exception. I'd prefer to write the tests from the perspective of any IEmployee and then be able to use the tests on any implementation of IEmployee.
Here's another example. I may also want to assert that setting the vacation time for any employee to a value less then zero throws and error. Yet I may also want to have different tests that apply to a specific concrete version of Employee. Say I want to test that Worker throws an exception if they are provided more then 14 days vacation, but a manager can be provided up to 36.
public interface IEmployee
{
string Name {get; set;}
int Number {get; set;}
}
public abstract class Employee:IEmploee
{
string Name {get; set;}
int Number {get;set;}
public abstract int VacationTime(get; set;)
}
public abstract class Worker:IEmployee
{
private int v;
private int vTime;
public abstract int VacationTime
{
get
{
return VTime;
}
set
{
if(value>36) throw new ArgumentException("Exceeded allowed vaction");
if(value<0)throw new ArgumentException("Vacation time must be >0");
vTime= value;
}
}
public void DoSomWork()
{
//Work
}
}
public abstract class Manager:IEmployee
{
public abstract int VacationTime
{
get
{
return VTime;
}
set
{
if(value>14) throw new ArgumentException("Exceeded allowed vaction");
if(value<0)throw new ArgumentException("Vacation time must be >0");
vTime= value;
}
}
public void DoSomeManaging()
{
//manage
}
}
So I guess what I'm looking for is a work flow that will allow me to nest unit tests. So for example when I test the Manager class I want to first test that it passes the Employee and IEmployee tests, and then test specific members such as DoSomeManaging().
I guess I know what you mean. I had the same issue.
My solution was to create a hierarchy also for testing. I'll use the same example you show.
First, have an abstract test class for the base IEmployee.
It has two main things:
i. All the test methods you want.
ii. An abstract method that returns the desired instance of the IEmployee.
[TestClass()]
public abstract class IEmployeeTests
{
protected abstract GetIEmployeeInstance();
[TestMethod()]
public void TestMethod1()
{
IEmployee target = GetIEmployeeInstance();
// do your IEmployee test here
}
}
Second, you have a test class for each implementation of IEmployee, implementing the abstract method and providing appropriate instances of IEmployee.
[TestClass()]
public class WorkerTests : IEmployeeTests
{
protected override GetIEmployeeInstance()
{
return new Worker();
}
}
[TestClass()]
public class ManagerTests : IEmployeeTests
{
protected override GetIEmployeeInstance()
{
return new Manager();
}
}
You can see everything works as expected and VS gives you the expected test methods for each WorkerTests and ManagerTests classes in the TestView window.
You can run them and have the test results for each implementation of the IEmployee interface, having to create the tests only in the base IEmployeeTests class.
You can always add specific test for the derived WorkerTests and ManagerTests classes.
The question would be now, what about classes that implement multiple interfaces, let's say EmployedProgrammer?
public EmployedProgrammer : IEmployee, IProgrammer
{
}
We don't have multiple inheritance in C#, so this is not an option:
[TestClass()]
public EmployedProgrammerIEmployeeTests : IEmployeeTests, IProgrammerTests
{
// this doesn't compile as IEmployeeTests, IProgrammerTests are classes, not interfaces
}
For this scenario, a solution is to have the following test classes:
[TestClass()]
public EmployedProgrammerIEmployeeTests : IEmployeeTests
{
protected override GetIEmployeeInstance()
{
return new EmployedProgrammer();
}
}
[TestClass()]
public EmployedProgrammerIProgrammerTests : IProgrammerTests
{
protected override GetIProgrammerInstance()
{
return new EmployedProgrammer();
}
}
with
[TestClass()]
public abstract class IProgrammerTests
{
protected abstract GetIProgrammerInstance();
[TestMethod()]
public void TestMethod1()
{
IProgrammer target = GetIProgrammerInstance();
// do your IProgrammerTest test here
}
}
I'm using this with good results.
Hope it helps.
Regards,
Jose
What I think you want to do is create unit tests for methods in abstract classes.
I'm not sure it makes sense to want to test a protected method on an abstract class, but if you insist simply extend the class in a class used exclusively for unittesting. That way you can expose the protected methods on the abstract class you want to test through public methods on the extending class that simply call through to the method on the abstract class.
If you have methods in abstract classes that you want unittested, I suggest refactoring them into separate classes and simply expose them as public methods and put those under test. Try looking at your inheritance tree from a 'test-first' perspective and I'm pretty sure you'll come up with that solution (or a similar one) as well.
It seems that you have described "composite unit testing" which is not supported by Visual Studio 2010 unit tests. Such things can be done in MbUnit according to this article. It is possible to create abstract tests in Visual Studio 2010 which is probably not exactly what you want. Here is description how to implement abstract tests in VS (Inheritance Example section).
Use microsoft moles for better testing. so you can mock the abstract base class / static methods etc easily. Please refer the following post for more info
detouring-abstract-base-classes-using-moles
BenzCar benzCar = new BenzCar();
new MCar(benzCar)
{
Drive= () => "Testing"
}.InstanceBehavior = MoleBehaviors.Fallthrough;
var hello = child.Drive();
Assert.AreEqual("Benz Car driving. Testing", hello);
The desire to run the same test against multiple classes usually means you have an opportunity to extract the behavior you want to test into a single class (whether it's the base class or an entirely new class you compose into your existing classes).
Consider your example: instead of implementing vacation limits in Worker and Manager, add a new member variable to Employee, 'MaximumVacationDays', implement the limit in the employee class' setter, and check the limit there:
abstract class Employee {
private int maximumVacationDays;
protected Employee(int maximumVacationDays) {
this.maximumVacationDays = maximumVacationDays
}
public int VacationDays {
set {
if (value > maximumVacationDays)
throw new ArgumentException("Exceeded maximum vacation");
}
}
}
class Worker: Employee {
public Worker(): Employee(14) {}
}
class Manager: Employee {
public Manager(): Employee(36) {}
}
Now you have only one method to test and less code to maintain.