Mocking classes with template methods - c++

Is there any pattern for testing classes that use classes containing template methods in public api? I know that in dynamic polymorphism mocking interface is the solution like this:
struct Interface {
virtual void foo() = 0;
virtual ~Interface() = default;
};
class TestedClass {
public:
TestedClass(Interface& i) {}
// ... rest of the class
};
struct IMock : public Interface {
void foo() override {}
};
void test() {
IMock bar;
TestedClass baz(bar);
}
But what can I do with something like below? Is there an idiomatic way to test this?
struct Interface {
template<class T>
void foo() {
// do stuff depending on type
}
};
class TestedClass {
public:
TestedClass(Interface& i) {}
// ... rest of the class
// uses Interface foo with multiple types
};

To allow mocking, in that case, you need
template <typename InterfaceT> class TestedClass;
so you can now have TestedClass<Interface> (for production) and TestedClass<MockInterface> (for testing).
struct Interface {
template<class T>
void foo() {
// do stuff depending on type
}
};
template <typename InterfaceT>
class TestedClass {
public:
TestedClass(InterfaceT& i) {}
// ... rest of the class
// uses Interface foo with multiple types
};
struct MockInterface {
template<class T>
void foo() {
// do mock-stuff depending on type
}
};
void test() {
MockInterface bar;
TestedClass baz(bar); // Or pre CTAD of C++17: TestedClass<MockInterface> baz(bar);
}

Related

C++ - Pushing variadic template class object into vector

class Base
{
public:
virtual void foo() = 0;
};
class A : public Base
{
public:
void foo() override { std::cout << "A\n"; }
};
class B : public Base
{
public:
void foo() override { std::cout << "B\n"; }
};
class Registry
{
public:
static Registry& instance()
{
static Registry s_instance;
return s_instance;
}
void register_foo(Base* foo)
{
m_vec.emplace_back(foo);
}
private:
std::vector<Base*> m_vec;
};
template<typename ... T>
class Foo : public T...
{
public:
Foo()
{
Registry::instance().register_foo(this);
}
void test() { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
f1->test();
f2->test();
}
As you can see I have a Base class, class A and class B.
A and B inherit from Base.
Class Foo is a template class, which is with a variadic template.
The idea is to be able to pass class A and class B into Foo.
Then this Foo is registered in the Registry class / pushed into a vector.
The problem is the following - as you can see I can have both Foo<A> and Foo<A, B>, or Foo<B, A>.
How can I have such a vector which can accept all possible types of Foo?
How about a simple common base class?
class FooBase {
public:
virtual ~FooBase() {}
virtual void test() = 0;
};
template<typename... T>
class Foo : public FooBase, public T...
{
public:
Foo() { }
void test() override { (T::foo(), ...); }
};
int main()
{
auto f1 = std::make_unique<Foo<A, B>>();
auto f2 = std::make_unique<Foo<A>>();
std::vector<std::unique_ptr<FooBase>> foos;
foos.push_back(std::move(f1));
foos.push_back(std::move(f2));
}
A std::vector holds one type of objects. You cannot put objects of different types into the same vector (and objects created from a template with different template arguments are different types).
One option (I'd not recommend it) is having a vector that holds instances of std::any) - works, but cumbersome and inefficient to work with. Another option is a vector of pointers to a common base class and taking advantage of polymorphism. A third option is simply having sepperate vectors for each type of object.

Inherit implementation of nested template class

my problem is a little bit weird and I'm not able to find an answer to it.
1) I do have a nested template class for my protocol
template <template<class TMessage> class TFrame, class TMessage>
class Protocoll
{
...
}
2) I do have an implementation for my frame and message
class MessageImpl : public Message
{
...
}
class FrameImpl : public Frame<MessageImpl>
{
...
}
3) Now I want to implement my protocol using the implementations for frame and message.
class ProtocolImpl : public Protocol<FrameImpl, MessageImpl>
{
...
}
The compiler complains about the first template Parameter "FrameImpl", because it is (obviously) no generic template type any more.
Is there any possibility to make this compile?
I don't want to make my 'FrameImpl' generic/template because than I would need to implement it in the header.
Thanks a lot
Edit:
Because of requesting a complete sample:
//--------------------- definitions
class Message
{
public:
virtual ~Message() = default;
virtual void foo() noexcept = 0;
};
template <class Message>
class Frame
{
public:
virtual ~Frame() = default;
virtual void foo() noexcept = 0;
};
template <template<class TMessage> class TFrame, class TMessage>
class Protocol
{
public:
virtual ~Protocol() = default;
virtual void foo() noexcept;
};
//--------------------- implementations
class MessageImpl : public Message
{
public:
void foo() noexcept
{ }
};
class FrameImpl : public Frame<MessageImpl>
{
public:
FrameImpl()
: message{ }
{ }
void foo() noexcept
{
message.foo();
}
private:
MessageImpl message;
};
class ProtocolImpl : public Protocol<FrameImpl, MessageImpl>
{
};
in the declaration of "ProtocolImpl", I could pass Frame as template type, but not FrameImpl.
You can do
template <typename>
using FrameImplT = FrameImpl;
class ProtocolImpl : public Protocol<FrameImplT, MessageImpl>
{
// ...
};
But think at what is the purpose of those template parameters.

Template class on a abstract class

So I have a class template Foo:
template <typename T>
class Foo
{
public:
Foo();
~Foo();
//...
};
I have two derived classes from the Foo class:
class FooDerived1 : public Foo<int>
{
public:
FooDerived1 ();
~FooDerived1 ();
};
class FooDerived2 : public Foo<double>
{
public:
FooDerived2 ();
~FooDerived2 ();
};
But now I saw that the class template was being used on a abstract class IBar like this:
class Foo;
class IBar
{
public:
virtual void placeFoo(Foo& foo) = 0; //error
virtual void removeFoo(Foo& foo) = 0;
};
I know I cannot use templates classes in abstract virtual classes.
But..in a case like this, what should I do?
I really need the IBar abstract class like this...
Forget the usage of template classes?
Option 1: Make IBar itself a template class.
template <class T>
class Foo;
template <class T>
class IBar
{
public:
virtual void placeFoo(Foo<T>& foo) = 0;
virtual void removeFoo(Foo<T>& foo) = 0;
};
Option 2: Make all Foo<T> derive from a common, non-generic FooBase.
class FooBase
{
// ...
};
template <typename T>
class Foo : public FooBase
{
public:
Foo();
~Foo();
//...
};
// ...
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0;
virtual void removeFoo(FooBase& foo) = 0;
};
The viability of both solutions depends on how much you actually depend on the T type. But that's what you should expect when you mix virtual functions with templates. With option 1, you do not have a common interface type anymore; with option 2, FooBase cannot provide any member function with a T-dependent argument.
By the way, don't forget about virtual destructors in your real code.
If you need common behaviour, create base class for all instances of Foo<>:
class FooBase
{
//common interface and data
};
template <class T>
class Foo : public FooBase
{
};
And then:
class FooBase;
class IBar
{
public:
virtual void placeFoo(FooBase& foo) = 0; //ok
virtual void removeFoo(FooBase& foo) = 0;
};
The thing is, that you try to mix templates (compile time) and dynamic polymorphism (runtime), which can be problematic (is it what you meant by "I know I cannot use templates classes in abstract virtual classes"?).
Why not stick to using templates?
class IBar
{
public:
template <class T>
void placeFoo(Foo<T>& foo);
template <class T>
void removeFoo(Foo<T>& foo);
};
or:
template <class T>
class IBar
{
public:
void placeFoo(Foo<T>& foo);
void removeFoo(Foo<T>& foo);
};

Is a C++ template able to "forward any class function" from parent class?

class Foo {
public:
void methodA();
};
class ManagedFoo {
Foo fooInst;
public:
void methodA() { doSomething(); fooInst.methodA();}
};
Now I want to make ManagedFoo as a template, managing any class not only Foo, and before any of Foo's function is called, call doSomething first.
template<typename _TyManaged>
class Manager {
_TyManaged _managedInst;
void doSomething();
public:
/*Forward every function called by _managedInst*/
/*How to write this?*/
};
I want to make it the same, make it replaceable between this two class, like this :
Foo* foo = new Foo();
foo->methodA();
Manager<Foo> managedFoo = new Manager<Foo>();
managedFoo->methodA(); //Hope it call Manager::doSomething() first then call _managedInst.methodA();
Can C++11 template do such thing? if answer is yes, how to?
Solution based on operator-> overloading:
#include <iostream>
#include <memory>
class A {
public:
void foo() { std::cout << "foo\n"; }
void bar() { std::cout << "bar\n"; }
};
template <typename T>
class ManagedBase {
std::shared_ptr<T> _inst;
public:
ManagedBase(const std::shared_ptr<T> inst) : _inst(inst) { }
virtual ~ManagedBase() { }
std::shared_ptr<T> operator->() {
before();
return this->_inst;
}
virtual void before() =0;
};
template <typename T>
class ManagedPrint : public ManagedBase<T> {
public:
ManagedPrint(const std::shared_ptr<T> inst) : ManagedBase(inst) { }
virtual void before() {
std::cout << "Said: ";
}
};
int main() {
auto ma = ManagedPrint<A>(std::make_shared<A>());
ma->bar(); // Said: foo
ma->bar(); // Said: bar
}
Something like this?
template<typename _TyManaged>
class Manager {
_TyManaged _managedInst;
void doSomething();
public:
_TyManaged* operator->() {
doSomething();
return &_managedInst;
}
};
This can solve your problem. But I'm still not sure what you want to do with your Manager class.
class Foo {
public:
void methodA();
};
template<typename T>
class ManagedFoo : public T {
public:
// some further extensions
};
And of course in this way you change the semantic of the Foo class by the manager from:
It has a
to
It is a
So I'm not sure if this is true in your case.

C++ template instantiation restrictions

I have a method foo in class C which either calls foo_1 or foo_2.
This method foo() has to be defined in C because foo() is pure virtual in BaseClass and I actually
have to make objects of type C. Code below:
template <class T>
class C:public BaseClass{
void foo() {
if (something()) foo_1;
else foo_2;
}
void foo_1() {
....
}
void foo_2() {
....
T t;
t.bar(); // requires class T to provide a method bar()
....
}
};
Now for most types T foo_1 will suffice but for some types foo_2 will be called
(depending on something()). However the compiler insists on instantiating both foo_1
and foo_2 because either may be called.
This places a burden on T that it has to provide
a bar method.
How do I tell the compiler the following:
if T does not have bar(), still allow it as an instantiating type?
you could use boost.enable_if. something like this:
#include <boost/utility/enable_if.hpp>
#include <iostream>
struct T1 {
static const bool has_bar = true;
void bar() { std::cout << "bar" << std::endl; }
};
struct T2 {
static const bool has_bar = false;
};
struct BaseClass {};
template <class T>
class C: public BaseClass {
public:
void foo() {
do_foo<T>();
}
void foo_1() {
// ....
}
template <class U>
void foo_2(typename boost::enable_if_c<U::has_bar>::type* = 0) {
// ....
T t;
t.bar(); // requires class T to provide a method bar()
// ....
}
private:
bool something() const { return false; }
template <class U>
void do_foo(typename boost::enable_if_c<U::has_bar>::type* = 0) {
if (something()) foo_1();
else foo_2<U>();
}
template <class U>
void do_foo(typename boost::disable_if_c<U::has_bar>::type* = 0) {
if (something()) foo_1();
// I dunno what you want to happen if there is no T::bar()
}
};
int main() {
C<T1> c;
c.foo();
}
You could create an interface for foo_1 and foo_2, such as:
class IFoo
{
public:
virtual void foo_1()=0;
virtual void foo_2()=0;
};
template <typename T>
class C : public BaseClass, public IFoo
{
void foo()
{
if (something())
foo_1();
else
foo_2();
}
};
template <typename T>
class DerivedWithBar : C<T>
{
public:
void foo_1() { ... }
void foo_2()
{
...
T t;
t.bar(); // requires class T to provide a method bar()
...
}
};
template <typename T>
class DerivedNoBar : C<T>
{
public:
void foo_1() { ... }
void foo_2() { ... }
};
I think the easiest way is to simply write a separate function template that 'C' can call:
template <class T>
void call_bar(T& /*t*/)
{
}
template <>
void call_bar<Something>(Something& t)
{
t.bar();
}
The original 'C' class can be modified accordingly:
void foo_2() {
....
T t;
call_bar(t); // does not require T to provide bar()
....
}
This has the downside that you have to explicitly define which types of T provide a bar method, but that's pretty much inevitable unless you can determine something at compile-time about all the types that do provide a bar method in their public interface or modify all these bar-supporting types so that they do share something in common that can be determined at compile-time.