我想问一下如何在下一个例子中使用rhino mocks:
Public Class CustomerService
{
Public void Register()
{
Action1();
Action2();
}
private action1 ()
{
//this is a call to other dll.
var isExist = _dataComponentService.CheckIfUserExist(userName);
}
private action2()
{
//do some more work...
// Call to dataComponentService. write some data in the database....
}
}
这只是我需要更新的实际代码的一个示例。 当前的单元测试正在对数据库服务进行真正的调用。 我想编写一个单元测试来检查公共Register()中的行为,而不需要对数据库服务进行真正的调用。
是否可以模拟对位于私有方法中的其他组件的调用,而无需重新编写漏洞服务?
先谢谢你
大利
答案 0 :(得分:3)
你需要做一些依赖注入才能让你的模拟进入你的被测试阶段(有关DI的更多信息,请查看Martin Fowler的this article)。首先,你的'dataComponentService'类需要实现一个接口:
public interface IDataComponentService
{
boolean CheckIfUserExist(String user);
}
然后,您可以通过添加适当的构造函数将实现该接口的类注入到CustomerService类中:
public class CustomerService
{
private IDataComponentService _dataComponentService
// This constructor allows you to inject your dependency into the class
public CustomerService(IDataComponentService dataComponentService)
{
_dataComponentService = dataComponentService;
}
Public void Register()
{
Action1();
Action2();
}
private action1 ()
{
//this is a call to other dll.
var isExist = _dataComponentService.CheckIfUserExist(userName);
}
private action2()
{
//do some more work...
// Call to dataComponentService. write some data in the database....
}
}
现在,在您的测试代码中,您可以创建一个IDataComponentService的模拟...
var dataComponentServiceMock = MockRepository.GenerateMock<IDataComponentService>();
//add mock's behavior here...
...并将其传递到您的考试中......因此......
var objUt = new CustomerService(dataComponentServiceMock);
objUt.Register();
// check method calls to the mock here...
答案 1 :(得分:2)
你的问题引起了我的怀疑。 一:单元测试不是单元测试,如果它正在执行数据库访问。如果它正在进行数据库访问,则更像是集成测试。 二:你应该更多地依赖依赖注入,并开始编程接口而不是对象。这意味着您注入了必须为_datacomponentservice
定义的接口除此之外。即使你有私人方法。您可以放松它,也许可以保护并使其成为虚拟。如果它是虚拟的,您可以使用不同的方式创建类的特殊测试版本。
许多人正在定义许多私人方法,但我发现有时这会阻碍未来的发展,我宁愿让它们受到保护而不是私有。因为你永远不知道未来会怎样。我使用例如.NET反射器来浏览微软代码,例如组合框,想要使它更灵活。我有时会这么做,因为有些方法和类甚至无法在派生类中访问。