0

I am writing a unit test for A::some_method() which accepts class B as follows:

class A {
public:
    some_method(B (&obj)[a_big_number]);
} 

Class B (Bad Class) has an ugly interface:

class B {
public: 
    get_value(int index);
    set_value(int index, value);
}

The reason I don't like this interface is that get_value(i) does not map to the same element as set_value(i). Someone thought it was a good idea to have a complicated mapping to the underlying array when getting the value. This mapping is created and developed by some third class C, which is not relevant here.

This means I either need to reverse engineer this unrelated mapping in order enter test data into class B, or somehow bypass it.

To bypass the complicated mapping, I want to create a subclass called B_Mock, as follows:

class B_Mock: public B {
public:
    get_value(int index) {/*code that just returns the index referenced by set_value(index)*/}
}

And then instantiate it in my unit test as:

A a;
B_Mock inputs_outputs[1000];
/* code that repeatedly calls set_value() for each element of inputs_outputs with an initial value. */

Once inputs_outputs is set up, I want to call a.some_method(inputs_outputs) to verify that that some_method() works correctly.

Here are my issues:

  • If I simply call a.some_method(inputs_outputs), I get the following compiler error:

    a reference of type "A (&)[1000]" (not const-qualified) cannot be initialized with a value of type "B_Mock [1000]"'

  • I cannot change the interface of A::some_method() to A::some_method(const B (&obj)[a_big_number]), because some_method() calls obj[index].set_value().

  • It does compile successfully if I change the interface of A::some_method() to A::some_method(const B obj[a_big_number]) and pass by value. I do not want to do this, since (1) obj is a rather large array of large objects, and (2) I need to access the modified data in inputs_outputs after a.some_method() operates on it, to verify that updates were made correctly. Passing by value will not return the modified objects.

How do I pass in my subclassed B_Mock to A.some_method() in a way that allows me to see the modified objects via the inputs_outputs parameter?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Chad Hicks
  • 11
  • 1
  • 3
    I strongly recommend not using fantasy code in your examples. Use real examples, and in the cases where you really don't know what something should look like in C++ be brutally obvious about it and try your best. – user4581301 Aug 21 '20 at 22:19
  • 1
    What you are attempting to do will not work. `A::some_method()` takes a a reference to a `B[]` array of objects. You can't give it any `B_Mock` objects, as they will get [sliced](https://stackoverflow.com/questions/274626/) when put into a `B[]` array. Besides, `B_Mock` won't work anyway unless `B::get_value()` is `virtual`. What you would have to do instead is dynamically patch `B` at runtime to point `B::get_value()` at another implementation, such as with a detour. – Remy Lebeau Aug 21 '20 at 22:21
  • Arrays are not polymorphic. Your third example compiles because you’re passing a pointer instead of an array, but it has undefined behaviour. – molbdnilo Aug 21 '20 at 22:23
  • 1
    The error message about initializing `A (&)[1000]` does not match the code show. Are you sure the message does not say `B (&)[1000]` instead? – Remy Lebeau Aug 21 '20 at 22:32

0 Answers0