2017-02-28 1 views
3

인터페이스에 삭제 된 copy-ctor가있는 객체를 만드는 함수가 있다면이 함수를 모의하는 방법은 무엇입니까? Gmock은 개체의 복사 생성자를 내부적으로 사용하는 것으로 보입니다.모의 메소드는 삭제 된 copy-ctor가있는 객체를 반환합니까?

예.

// The object with deleted copy-ctor and copy-assignment 
class TTest 
{ 
public: 
    TTest() = delete; 
    TTest(const TTest&) = delete; 
    TTest& operator=(const TTest&) = delete; 
    TTest(TTest&&) = default; 
    TTest& operator=(TTest&&) = default; 

    explicit TTest(int) { 
    } 
}; 

// My interface to mock 
class MyInterface 
{ 
    public: 
     virtual ~MyInterface() {} 
     virtual TTest GetUniqueTest() = 0; 
}; 

// The mock 
class MockMyInterface: public MyInterface{ 
    public: 
     MOCK_METHOD0(GetUniqueTest, TTest()); 
} 

컴파일 오류가 말한다 :이 방법은 std::unique_ptr<T>을 반환

gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)' 
    T retval(value_); 
... 
gmock/gmock-actions.h:190:52: error: use of deleted function 'TTest::TTest(const TTest&)' 
     internal::BuiltInDefaultValue<T>::Get() : *value_; 
... 
gmock/internal/gmock-internal-utils.h:371:71: error: use of deleted function 'TTest::TTest(const TTest&)' 
     *static_cast<volatile typename remove_reference<T>::type*>(NULL)); 

경우 std::unique_ptr<T>뿐만 아니라 복사의 ctor를 삭제 한 이후, 오류가 동일합니다.

내 질문은 : 어떻게 삭제 된 복사 - ctors와 함께 개체를 반환 같은 방법 모의?

저는 googletest v1.7, GCC 5.3.0 및 Ubuntu 14.04.1을 사용하고 있습니다.

답변

3

Google 테스트 1.8은 Mine의 의견에서 언급했듯이 이러한 기능 조롱을 지원하는 것으로 보입니다 (documentation).

1.7에 대해서는 해결책 here을 찾았습니다.

첫째, 비 복사 가능한 객체를 포장하는 유틸리티 클래스를 만들 :

template <typename T> 
class Mover 
{ 
public: 
    Mover(T&& object) 
     : object(std::move(object)), 
     valid(true) 
    { 
    } 

    Mover(const Mover<T>& other) 
     : object(const_cast<T&&>(other.object)), 
     valid(true) 
    { 
     assert(other.valid); 
     other.valid = false; 
    } 

    Mover& operator=(const Mover& other) 
    { 
     assert(other.valid); 
     object = const_cast<T&&>(other.object); 
     other.valid = false; 
     valid = true; 
    } 

    T& get() 
    { 
     assert(valid); 
     return object; 
    } 

    const T& get() const 
    { 
     assert(valid); 
     return *object; 
    } 

private: 
    T object; 
    mutable bool valid; 
}; 

template <typename T> 
inline Mover<T> Movable(T&& object) 
{ 
    return Mover<T>(std::move(object)); 
} 

을하고 만들 프록시 모의 :

class MockMyInterface : public MyInterface 
{ 
public: 
    MOCK_METHOD0(GetUniqueTest_, Mover<TTest>()); 
    TTest GetUniqueTest() 
    { 
     return std::move(GetUniqueTest_().get()); 
    } 
} 
+0

멋진 대답은, 그것을 잘 작동합니다! – Mine

+0

Google 테스트 ** 1이 나에게 온다.8 **는 이러한 기능 조롱을 지원합니다. https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#mocking-methods-that-use-move-only-types googletest v1.8로 업데이트하는 것이 좋습니다. – Mine

+0

@Mine 예, 나도 나중에 발견했는데 확인할 시간이 없었습니다 :) 아마도 당신이 자기 결정을 할 수 있다고 확신 할 때) – BartoszKP

1
여기에 내 자신의 질문에 대답

단지 업데이트 된 정보를 제공 할 수 있습니다.

googletest 릴리스 1.8.0 이상을 사용하여 ByMove(...)을 소개하고 기본적으로 복귀 이동 전용 유형을 지원합니다.

그래서 코드는 OK 컴파일 :

class MockMyInterface: public MyInterface{ 
    public: 
     MOCK_METHOD0(GetUniqueTest, TTest()); 
} 

그러나 gmock 기본 TTest 반환하는 방법을 알고하지 않기 때문에 런타임에 예외가 발생합니다 :

C++ exception with description "Uninteresting mock function call - returning default value. 
    Function call: GetUniqueTest() 
    The mock function has no default action set, and its return type has no default value set." thrown in the test body. 

이 쉽게 설정하여 해결 될 수 모의 수업의 기본 동작 :

ON_CALL(*this, GetUniqueTest()).WillByDefault(Return(ByMove(TTest(0)))); 

참고 : std::unique_ptr<T>의 경우 기본 생성자가 있기 때문에 정상입니다. nullptrunique_ptr이 기본적으로 반환됩니다. googletest 1.8.0를 사용하는 경우

그래서, 모두 함께 퍼팅 이상, 우리는 할 수 있습니다

// My interface to mock 
class MyInterface 
{ 
    public: 
     virtual ~MyInterface() {} 
     virtual TTest GetUniqueTest() = 0; 
     virtual std::unique_ptr<int> GetUniqueInt() = 0; 
}; 

// The mock 
class MockMyInterface: public MyInterface{ 
    public: 
     MOCK_METHOD0(GetUniqueTest, TTest()); 
     MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>()); 
     MockMyInterface() { 
      ON_CALL(*this, GetUniqueTest()) 
       .WillByDefault(Return(ByMove(TTest(0)))); 
     } 
}; 

이 참조가 : Mocking Methods That Use Move-Only Types

관련 문제