2013-07-09 147 views
0

即时通讯使用.net mvc3构建简单的应用程序。我写了几个测试用例,我遇到了其中一个问题。即时通讯使用起订量来嘲笑我的域名服务,我有这个两个方法:模拟方法不会返回对象

List<Customer> customersRepo = 
{ 
    new Customer{ 
    Id = 0, 
    Name = "Jojo" 
    }, 
    new Customer{ 
    Id = 1, 
    Name = "John" 
    } 
} 

mock.Setup(m => m.GetByName(IsAny<string>())).Returns<string>(
n => 
customersRepo.Where(c => c.Name == n) 
); 

mock.Setup(m => m.GetById(IsAny<int>())).Returns<int>(
    n=> 
    customersRepo.Where(c => c.Id == n) 
); 

的问题是,当我使用模拟对象的方法,通过名字来获取客户的我得到一个我问了,但是当我尝试以ID获取我总是从模拟对象中获得空对象..我试图与ID 0和1 ..可能是什么问题?

感谢

+1

我不能相信这些设置按预期工作。这两个设置都返回一个'IEnumerable ',但一个表示它返回一个'string',另一个表示它返回一个'int'。这两者都不是'IEnumerable '。 –

回答

1

我觉得你应该返回第一个或默认的客户:

mock.Setup(m => m.GetById(IsAny<int>())).Returns<int>(
    id => 
    customersRepo.FirstOrDefault(c => c.Id == id) 
); 

也请记住,你并不需要在嘲笑重新实现资源库的逻辑(即怪异非常脆弱)。这是模拟。你可以嘲笑任何你想要的结果,没有任何逻辑:

mock.Setup(m => m.GetById(42)).Returns<int>(new Customer { Id = 42 }); 

使用嘲笑验证互动 - 即你的资料库被称为预计法预计参数的客户。


如果你想测试一些服务的业务逻辑,那么服务是一个被测系统(SUT),你不应该嘲笑它。但是,如果你的服务同时具有业务逻辑和数据访问逻辑,那么它做的事情太多了。提取数据访问逻辑一些仓库类,它将实现接口:

public interface ICustomerRepository 
{ 
    Customer GetById(int id); 
    // other methods related to customr data access 
} 

然后,让你的服务依赖于该接口上(依赖倒​​置):

public class YourService 
{ 
    private readonly ICustomerRepository _repository; 
    // dependency injection 
    public YourService(ICustomerRepository repository) 
    { 
     _repository = repository; 
    } 

    public void ExecuteSomeBusinessLogic() 
    { 
     // your code will go here 
    } 
} 

然后写服务的测试。因此,服务需要依赖性(客户存储库),你应该嘲笑这种依赖性。并按照您的预期验证服务与依赖关系进行交互。例如。在ExecuteSomeBusinessLogic测试中,我们应该检查该服务会询问顾客,ID为42(是的,怪异的业务逻辑):

[Test] 
public void ShouldPerformGoodStuffWhenCustomerFound() 
{ 
    // Arrange 
    var mockRepository = new Mock<ICustomerRepository>(); 
    mockRepository.Setup(r => r.GetById(42)).Returns(new Customer { Id = 42 }); 
    var service = new YourService(mockRepository.Object); 
    // Act 
    service.ExecuteSomeBusinessLogic(); 
    // Assert 
    mockRepository.VerifyAll(); 
    // check other stuff 
} 

如果你写的情况下测试时,没有在数据库中找到自定义,只安装不同的回报:

mockRepository.Setup(r => r.GetById(42)).Returns(null); 
+0

我已经在LINQ结束时尝试了FirstOrDefault(),这也不是我的存储库逻辑在这里..我只是模拟数据存储作为列表,并有少量记录..然后我嘲笑我的客户服务,以便进行单元测试。然而,我会改变这样做的方式,我会添加新用户(准备测试),然后生病尝试使用该方法) – stefo0O0o

+0

mock.Setup(m => m.GetCustomerById(It.IsAny ()) ).Returns ( id => customersRepo.FirstOrDefault(c => c.Id == id) ); – stefo0O0o

+0

这是什么意思返回,我在互联网上看到,返回中的泛型类型实际上是我想要在模拟方法内部接收的参数的类型,所以我可以根据该参数采取行动,即int是实际的id当我在模拟对象上调用GetById方法时发送的。 – stefo0O0o

0

我其实只是改了一下我的基础设施..现在我的服务中获得的DataSource接口对象在构造函数中..这是独立的数据源,并依靠它来获得客户对象,OFC。在它检查业务规则并执行任何需要的用户输入清洁之后。现在,我将在单元测试中嘲笑我的数据源(一个包含客户对象的列表),并使用此嘲笑的回购为我的服务提供一个实例的客户对象..这样我可以测试我已经编码的服务业务逻辑的正确性。之前我已经将该服务与特定的数据存储(即使用EF DbContext的数据库)相结合,并且在单元测试中使用该服务有点困难,因为它已经与数据库耦合了,但我不想更改和恢复db状态只是为了执行我的单元测试,所以我想用简单的客户对象列表来模拟数据存储。感谢您的努力,帮助我在那里:)

相关问题