Menu

#39 Mocking interface hierarchies is tedious

closed
None
2014-11-11
2013-11-08
legalize
No

Interface hierarchies are pretty common. However, mocking a derived interface in an interface hierarchy requires me to repeat all the methods of the base classes and there isn't an easy way to specify just the extensions to an existing mock.

Consider the following:

class IUnknown {
    virtual ~IUnknown() { }

    virtual ULONG AddRef() = 0;
    virtual ULONG Release() = 0;
    virtual HRESULT QueryInterface(REFIID iid, void **result) = 0;
};

class ID3D11DeviceChild : public virtual IUnknown {
    virtual ~ID3D11DeviceChild() { }

    virtual void GetDevice(ID3D11Device **result) = 0;
    virtual HRESULT GetPrivateData(REFGUID guid, UINT *size, void *data) = 0;
    virtual HRESULT SetPrivateData(REFGUID guid, UINT size, void const *data) = 0;
    virtual HRESULT SetPrivateDataInterface(REFGUID guid, IUnknown const *data) = 0;
};

class ID3D11Resource : public virtual ID3D11DeviceChild {
    virtual ~ID3D11Resource() { }

    virtual UINT GetEvictionPriority() = 0;
    virtual void GetType(D3D11_RESOURCE_DIMENSION *type) = 0;
    virtual void SetEvictionPriority(UINT value) = 0;
};

class ID3D11Texture1D : public virtual ID3D11Resource {
    virtual ~ID3D11Texture1D() { }

    virtual void GetDesc(D3D11_TEXTURE1D_DESC *result) = 0;
};

In order to mock ID3D11Texture1D with turtle, I have to mock all the methods of the base classes as well as ID3D11Texture1D. This is fine if I only need to mock one of the most-derived interfaces in an interface hierarchy. However, as soon as I also need to mock ID3D11Texture2D which similarly derived from ID3D11Resource, now I have to duplicate all the base class methods in the new mock. This is repetitive and boring. I would rather that the mock framework allow me to build a hierarchy of mocks just like I have a hierarchy of interfaces.

Discussion

  • Mathieu Champlon

    Hi,

    If I understand you right, you can simply do:

    MOCK_BASE_CLASS( MockResource, ID3D11Resource )
    {
        // ...
    };
    
    struct MockTexture1D : MockResource, ID3D11Texture1D
    {
        MOCK_METHOD( GetDesc, 1, void(D3D11_TEXTURE1D_DESC*) )
    };
    
    struct MockTexture2D : MockResource, ID3D11Texture2D
    {
        MOCK_METHOD( GetDesc, 1, void(D3D11_TEXTURE2D_DESC*) )
    };
    

    This is somewhat documented in http://turtle.sourceforge.net/turtle/reference.html#turtle.reference.creation.class but maybe it should be highlighted better ?

    MAT.

     
  • Mathieu Champlon

    • status: open --> pending
    • assigned_to: Mathieu Champlon
     
  • legalize

    legalize - 2013-11-09

    I'll take a look at the approach you suggest; am I prevented from using

    MOCK_METHOD(GetDesc, 1);
    

    for some reason?

     
  • Mathieu Champlon

    Yes, this is because in order to use the shorter MOCK_METHOD form you need either to use MOCK_BASE_CLASS or have a typedef ID3D11Texture1D base_type (this is again documented at the same location as the link above).
    You could in theory use MOCK_BASE_CLASS again e.g.

    MOCK_BASE_CLASS( MockTexture1D, ID3D11Texture1D ), MockResource
    {
        MOCK_METHOD( GetDesc, 1 )
    };
    

    However I just realized this doesn't work at the moment because I forgot to inherit virtually from mock::object in mock.hpp (I fixed it but didn't commit it yet).
    Although the notation is a bit awkward and not documented for now, I might as well do it though as I didn't do it until now only to leave me some room to tweak the macro but it is likely to remain as it is now.

    MAT.

     
  • Mathieu Champlon

    Actually the virtual inheritance doesn't help much, I'm going to revert it...

    MAT.

     
  • legalize

    legalize - 2013-11-13

    I thought the rule-of-thumb was that you virtually inherit from interfaces and inherit from implementations.

     
  • Mathieu Champlon

    Yes I suppose so, it was a dead end anyway for the problem to solve...

     
  • Mathieu Champlon

    • status: pending --> closed
     

Log in to post a comment.