at the moment I'm writing a test-driven project, and I stuck in testing the following behaviour.
I got an interface called Menu
to which one can add dynamically entries through an addEntry
-Method. There is another class which contains the Menu
object. Let's call it MenuPresenter
. When a specific method (e.g. someAction(string title)
) is called the MenuPresenter
should instantiate an Entry
object with the received title and add it to the Menu
object. The instantiation of the Entry
object happens in a factory method inside the MenuPresenter
.
The tested behaviour should be WhenSomeActionIsCalledShouldAddAnEntryContainingTitleToMenu
But I don't find the right way to write the test. I figured out two main possibilities to test it, but i actually don't like both of them because of the (later) mentioned disadvantages.
- Implement a MenuSpy inheriting from Menu, which has a getAddedEntry-Method. Like this you can extract the added
Entry
and check the state of the object
EXPECT_TRUE(entry->getTitle() == title);
Disadvantages: To check the state of the Entry
object I have either to extend the API of the Interface with getter-Methods which are only used for testing reasons or to use public member variables. This allow every client get access to the internal structure of each Implementation of Entry
. Thus the clients are coupled to internal structure.
- Extend the system through an
EntryFactory
interface which has a
makeEntry(std::string title)
-method. Like this one can implement anEntryFactorySpy
and can check if themakeEntry
-method is called with the correct parameters (title). In another Test we can implement anEntryFactoryStub
which returns a specificEntry
object. Then we can check (via aMenuSpy
) if theMenuPresenter
has added the received entry from the factory to the menu. The instantiation of theEntry
object is then tested in a unit test for a the factory.
Disadvantages: Because I test the call of the factory's makeEntry
-method the algorithm of using a factory to create entries is fix. The test is tightly coupled to the internal structure of the MenuPresenter
. Changing the algorithm (e.g. using now the factory method would break the test, without that the expected behaviour of the application breaks.
For application's behaviour it should be unimportant if the MenuPresenter
creates the Entry
itself of if it uses a EntryFactory
. This is why I'd prefer the first way. But I don't want the client's of Entry
to be coupled to the internal structure of Entry
only because of testing reasons.
This is only an example of my problem. In reality the entry not only created with a string. It gets other complex objects as shared_ptr. This is another reason, why I dont want to use public getter-methods. Like this one could extract the complex object from the Entry
and change it (Yes, I could give out a const shared_ptr, but this seems to be not a good practice to me.)
The Question is, does anyone know a testing pattern or a solution that adresses my problem? Meaning testing if a correct Entry
object is added to the Menu
object without being coupled to tight to the algorithm or the internal structure of Entry
?
Thanks, Janis
Aucun commentaire:
Enregistrer un commentaire