Doug R..
78
我建议嘲笑你对数据库的调用.模拟基本上是看起来像你试图调用方法的对象的对象,因为它们具有调用者可用的相同属性,方法等.但是,当调用特定方法时,它不会执行他们编程要执行的任何操作,而是完全跳过它,并返回结果.该结果通常由您提前定义.
为了设置对象进行模拟,您可能需要使用某种控制/依赖注入模式的反转,如下面的伪代码:
class Bar
{
private FooDataProvider _dataProvider;
public instantiate(FooDataProvider dataProvider) {
_dataProvider = dataProvider;
}
public getAllFoos() {
// instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
return _dataProvider.GetAllFoos();
}
}
class FooDataProvider
{
public Foo[] GetAllFoos() {
return Foo.GetAll();
}
}
现在在单元测试中,您创建了一个FooDataProvider的模拟,它允许您调用方法GetAllFoos而无需实际命中数据库.
class BarTests
{
public TestGetAllFoos() {
// here we set up our mock FooDataProvider
mockRepository = MockingFramework.new()
mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);
// create a new array of Foo objects
testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}
// the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
// instead of calling to the database and returning whatever is in there
// ExpectCallTo and Returns are methods provided by our imaginary mocking framework
ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)
// now begins our actual unit test
testBar = new Bar(mockFooDataProvider)
baz = testBar.GetAllFoos()
// baz should now equal the testFooArray object we created earlier
Assert.AreEqual(3, baz.length)
}
}
简而言之,这是一种常见的模拟方案.当然,你仍然可能想要对你的实际数据库调用进行单元测试,为此你需要访问数据库.
模拟单元测试中的数据库调用有什么价值?它似乎没有用,因为您可以更改实现以返回不同的结果,但是您的单元测试将(错误地)通过。 (2认同)