IEntityRepository::GetEntities() and IEntityRepository::GetHost() not implementable in test_utils.h due to virtual inheritance of IVehicle
I tried to write a test for the TrafficSinkAction which uses the method IEntityRepository::GetEntities().
MockEntityRespository::GetEntities()
returns a const reference to its private member std::vector<std::unique_ptr<mantle_api::IEntity>> entities_{};
.
As there are no setters for this member, the mock is incomplete.
In addition, the mock offers a private member MockVehicle test_vehicle_{};
which is, of course, of base type IVehicle
.
I wanted to put the test_vehicle_ into the entities_ collection, so that the mock is "coherent".
// DELETE THIS: MockVehicle test_vehicle_{};
std::vector<std::unique_ptr<mantle_api::IEntity>> entities_{std::make_unique<MockVehicle>() /* test_vehicle_ */};
In order to access the mock, calling GetHost() would be convenient and simply return the first element of the collection.
mantle_api::IVehicle& GetHost() override {
return *(static_cast<mantle_api::IVehicle*>(entities_.front().get()));
}
Unfortunately, the type IVehicle
derives "virtually" from IEntity
and so, the upcast from IEntity
to IVehicle
is invalid (see https://gitlab.eclipse.org/eclipse/openpass/mantle-api/-/blob/master/include/MantleAPI/Traffic/i_entity.h#L86)
Look here for details: http://coliru.stacked-crooked.com/a/e8758c9b8d4dfacf
From my perspective this is a design flaw of Mantle. Entities should be "castable" to their specific interface, so that e.g. the following tests would be also possible
// pseudo-code for TrafficSinkAction
for(const auto& entity : repository.GetEntities())
{
// do not despawn static objects
if(!dynamic_cast<IStaticObject>(entity))
{
repository.delete(entity.GetUniqueId());
}
}
- What is the reasoning behind the virtual inheritance?
- How do I distinguish between the types of entities?
- Any other ideas?