当我尝试用我的生产c ++代码类和模拟对象编译单元测试时,我得到链接错误。我正在使用make文件和clang编译器(osx命令行)。
这是简化的例子。谢谢你能帮我解决这个问题。 文件夹结构如下:
生产代码 - >单元测试代码 - > Gmock和GTest文件夹
1)生产代码A类将进行单元测试。
myclass_a.h:
#ifndef MYCLASS_A_H
#define MYCLASS_A_H
#include "myclass_b.h"
class MyClass_A
{
public:
MyClass_A();
virtual void DoBThing();
private:
MyClass_B secondClass;
};
#endif // MYCLASS_A_H
myclass_a.cpp:
#include "myclass_a.h"
MyClass_A::MyClass_A()
{
}
void MyClass_A::DoBThing()
{
secondClass.DoThis();
}
2)生产代码类B.模拟对象将派生它。
myclass_b.h:
#ifndef MYCLASS_B_H
#define MYCLASS_B_H
class MyClass_B
{
public:
MyClass_B();
virtual void DoThis();
};
#endif // MYCLASS_B_H
myclass_b.cpp:
#include "myclass_b.h"
MyClass_B::MyClass_B()
{
}
void MyClass_B::DoThis()
{
}
3)单元测试代码
MyClassA_UT.cpp:
#include "Mock-MyClassB.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "../myclass_a.h"
TEST(ClassACategory,Test1)
{
MockMyClass_B classB;
EXPECT_CALL(classB, DoThis());
MyClass_A classA;
classA.DoBThing();
}
4)模拟对象
模拟-MyClassB.h:
#include "gmock/gmock.h" // Brings in Google Mock.
#include "../myclass_b.h"
class MockMyClass_B : public MyClass_B {
public:
MOCK_METHOD0(DoThis, void());
};
5)项目的Makefile(基本文件是从谷歌某处复制的):
# A sample Makefile for building both Google Mock and Google Test and
# using them in user tests. This file is self-contained, so you don't
# need to use the Makefile in Google Test's source tree. Please tweak
# it to suit your environment and project. You may want to move it to
# your project's root directory.
#
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.
# Please tweak the following variable definitions as needed by your
# project, except GMOCK_HEADERS and GTEST_HEADERS, which you can use
# in your own targets but shouldn't modify.
# Points to the root of Google Test, relative to where this file is.
# Remember to tweak this if you move this file, or if you want to use
# a copy of Google Test at a different location.
GTEST_DIR = ./gtest-1.7.0
# Points to the root of Google Mock, relative to where this file is.
# Remember to tweak this if you move this file.
GMOCK_DIR = ./gmock-1.7.0
# Where to find user code.
USER_DIR = ./
PRODUCTION_CODE_DIR = ../
# Flags passed to the preprocessor.
# Set Google Test and Google Mock's header directories as system
# directories, such that the compiler doesn't generate warnings in
# these headers.
CPPFLAGS += -isystem $(GTEST_DIR)/include -isystem $(GMOCK_DIR)/include
# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread
# All tests produced by this Makefile. Remember to add new tests you
# created to the list.
TESTS = UnitTest
# All Google Test headers. Usually you shouldn't change this
# definition.
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h \
$(GTEST_DIR)/include/gtest/internal/*.h
# All Google Mock headers. Note that all Google Test headers are
# included here too, as they are #included by Google Mock headers.
# Usually you shouldn't change this definition.
GMOCK_HEADERS = $(GMOCK_DIR)/include/gmock/*.h \
$(GMOCK_DIR)/include/gmock/internal/*.h \
$(GTEST_HEADERS)
# House-keeping build targets.
all : $(TESTS)
clean :
rm -f $(TESTS) gmock.a gmock_main.a *.o
# Builds gmock.a and gmock_main.a. These libraries contain both
# Google Mock and Google Test. A test should link with either gmock.a
# or gmock_main.a, depending on whether it defines its own main()
# function. It's fine if your test only uses features from Google
# Test (and not Google Mock).
# Usually you shouldn't tweak such internal variables, indicated by a
# trailing _.
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
GMOCK_SRCS_ = $(GMOCK_DIR)/src/*.cc $(GMOCK_HEADERS)
# For simplicity and to avoid depending on implementation details of
# Google Mock and Google Test, the dependencies specified below are
# conservative and not optimized. This is fine as Google Mock and
# Google Test compile fast and for ordinary users their source rarely
# changes.
gtest-all.o : $(GTEST_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GTEST_DIR)/src/gtest-all.cc
gmock-all.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GMOCK_DIR)/src/gmock-all.cc
gmock_main.o : $(GMOCK_SRCS_)
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) -I$(GMOCK_DIR) $(CXXFLAGS) \
-c $(GMOCK_DIR)/src/gmock_main.cc
gmock.a : gmock-all.o gtest-all.o
$(AR) $(ARFLAGS) $@ $^
gmock_main.a : gmock-all.o gtest-all.o gmock_main.o
$(AR) $(ARFLAGS) $@ $^
# Builds a sample test.
myclass_a.o : $(PRODUCTION_CODE_DIR)/myclass_a.cpp $(PRODUCTION_CODE_DIR)/myclass_a.h $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(PRODUCTION_CODE_DIR)/myclass_a.cpp
MyClassA_UT.o : $(USER_DIR)/MyClassA_UT.cpp $(GMOCK_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/MyClassA_UT.cpp
UnitTest : MyClassA_UT.o myclass_a.o gmock_main.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
6)链接错误:
ar rv gmock_main.a gmock-all.o gtest-all.o gmock_main.o
ar: creating archive gmock_main.a
a - gmock-all.o
a - gtest-all.o
a - gmock_main.o
c++ -isystem ./gtest-1.7.0/include -isystem ./gmock-1.7.0/include -g -Wall -Wextra -pthread -lpthread MyClassA_UT.o myclass_a.o gmock_main.a -o UnitTest
clang: warning: argument unused during compilation: '-pthread'
Undefined symbols for architecture x86_64:
"MyClass_B::DoThis()", referenced from:
MyClass_A::DoBThing() in myclass_a.o
"MyClass_B::MyClass_B()", referenced from:
MyClass_A::MyClass_A() in myclass_a.o
"MyClass_B::MyClass_B()", referenced from:
MockMyClass_B::MockMyClass_B() in MyClassA_UT.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [UnitTest] Error 1
如果我将B类对象添加到makefile,那么将调用B类的方法而不是mock方法。
编辑,如果我添加了B类,编译通过但测试用例失败:
./UnitTest
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from ClassACategory
[ RUN ] ClassACategory.Test1
.//MyClassA_UT.cpp:9: Failure
Actual function call count doesn't match EXPECT_CALL(classB, DoThis())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] ClassACategory.Test1 (0 ms)
[----------] 1 test from ClassACategory (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] ClassACategory.Test1