4
\$\begingroup\$

Here is my function I want to test:

template<typename T>
void free_items(std::vector<T*>& items)
{
    std::for_each(items.begin(), items.end(), [](T* (&item)){delete item; item = nullptr; });
}

I expect the each pointer in my result vector will be freed and be set null correctly. So I write down the following test code.

This is my mock class:

struct FreeItemMock
{
    FreeItemMock(bool& destroyed):m_destroyed (destroyed) {}
    ~FreeItemMock(){ m_destroyed = true;}
    bool& m_destroyed ;
};

Here is my test code:

BOOST_AUTO_TEST_CASE(test_free_items)
{
    bool destroyed[3] = {};
    std::vector<FreeItemMock*> mocks;

    mocks.push_back(new FreeItemMock(destroyed[0]));
    mocks.push_back(new FreeItemMock(destroyed[1]));
    mocks.push_back(new FreeItemMock(destroyed[2]));

    BOOST_CHECK_EQUAL(destroyed[0], false);
    BOOST_CHECK_EQUAL(destroyed[1], false);
    BOOST_CHECK_EQUAL(destroyed[2], false);

    free_items(mocks);

    BOOST_CHECK_EQUAL(destroyed[0], true);
    BOOST_CHECK_EQUAL(destroyed[1], true);
    BOOST_CHECK_EQUAL(destroyed[2], true);

    BOOST_CHECK(mocks[0] == nullptr);
    BOOST_CHECK(mocks[1] == nullptr);
    BOOST_CHECK(mocks[2] == nullptr);
}

The following are my questions:

  1. Is the my so-called FreeItemMock a mock or a stub? I am not sure whether I pick the right name on my testee-class. According to the book The art of unit testing with examples in C#. A mock is used to test whether the interaction with other classed happened. I use my FreeItemMock to test its destructor is called, but after invoke the free_item my FreeItemMock actually does not exist anymore. It looks the destroyed[3] array variable is more like a mock.

  2. The function I want to test is doing job on a vector, so I need to prepare a array of data to test. Is it correct to hand write a serious of fixture like data[0], data[1], data[2] and assert the result? Because the books also says a unit test should not have "logic" (like while, for-loop, if) to increase its complexity.

    Or should I make a testing utility to help me produce the array data, and make another test for the utility?

  3. Is it necessary to check the pre-test value of destroyed? Is it clearer to tell the reader that this function would make destroyed from 0 to 1? Or It is just too tedious?

\$\endgroup\$
2
\$\begingroup\$

I think that if you accept definition Fowler uses you should name them "stubs":

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information. (Mocks Aren't Stubs )

Given the structure of the code if you want to cover with a suite of test should at least test how it works under a large set of input:

  • Empty array
  • Single element array
  • Array filled with null element
  • Array with a arbitrary number of element

with a different test for each of this cases

For this reason I suppose you should write a function that "allocate" an array, to avoid code repetition in the test (also tests must have code that you can maintain!). So I think yes you should put all the logic that can help you inside the test.

I'm not a fan of test not that test themselves, but in this case all the test make sense only if you invoke FreeItemMock with a reference to a bool, so yes I think make sense to test it, but I suggest you put it destructor, before changing the value, in this you are sure that you transaction from false to true is a really transaction and not a false to false

\$\endgroup\$
  • \$\begingroup\$ 1. What is a # of element? 2. Should I separate 4 test cases according to different array items? Because the book also says one concern in one test. \$\endgroup\$ – Chen OT Oct 24 '14 at 10:50
  • 1
    \$\begingroup\$ I've extended the question to explain better this two points. Thank you for you comment! \$\endgroup\$ – lbenini Oct 24 '14 at 12:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.