lundi 20 mars 2017

Testing the creation of objects in a factory method

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.

enter image description here

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.

  1. 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.

  1. Extend the system through an EntryFactory interface which has a
    makeEntry(std::string title)-method. Like this one can implement an EntryFactorySpy and can check if the makeEntry-method is called with the correct parameters (title). In another Test we can implement an EntryFactoryStub which returns a specific Entry object. Then we can check (via a MenuSpy) if the MenuPresenter has added the received entry from the factory to the menu. The instantiation of the Entry 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 Menuobject without being coupled to tight to the algorithm or the internal structure of Entry?

Thanks, Janis

Aucun commentaire:

Enregistrer un commentaire