Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 模拟方法获胜';t返回对象_.net_Unit Testing_Moq - Fatal编程技术网

.net 模拟方法获胜';t返回对象

.net 模拟方法获胜';t返回对象,.net,unit-testing,moq,.net,Unit Testing,Moq,我正在使用.NETMVC3构建简单的应用程序。我写了几个测试用例,其中一个有问题。我使用Moq来模拟我的域服务,我有两种方法: List<Customer> customersRepo = { new Customer{ Id = 0, Name = "Jojo" }, new Customer{ Id = 1, Name = "John" } } mock.Setup(m => m.GetByName(IsAny<string&

我正在使用.NETMVC3构建简单的应用程序。我写了几个测试用例,其中一个有问题。我使用Moq来模拟我的域服务,我有两种方法:

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=0,
Name=“Jojo”
},
新客户{
Id=1,
Name=“约翰”
}
}
mock.Setup(m=>m.GetByName(IsAny())。返回(
n=>
CustomerRepo.Where(c=>c.Name==n)
);
mock.Setup(m=>m.GetById(IsAny())。返回(
n=>
CustomerRepo.Where(c=>c.Id==n)
);
问题是,当我使用mock对象的方法按名称获取customer时,我得到了我要求的那个,但是当我尝试按id获取时,我总是从mock对象中获取null对象。。我用id 0和1尝试了这两种方法。。有什么问题吗


谢谢

我认为您应该返回第一个或默认客户:

mock.Setup(m => m.GetById(IsAny<int>())).Returns<int>(
  id =>
  customersRepo.FirstOrDefault(c => c.Id == id)
);
然后使您的服务依赖于此接口(依赖倒置):

然后为服务编写测试。因此,服务需要依赖关系(客户存储库),您应该模拟此依赖关系。并验证服务是否按预期与依赖项交互。例如,在您的ExecuteSomeBusinessLogic测试中,我们应该检查服务是否会请求id等于42的客户(是的,奇怪的业务逻辑):


实际上,我只是稍微改变了一下我的基础设施。。现在,我的服务在构造函数中获取数据源接口对象。。这是一个独立的数据源,它依赖它来获取客户对象,ofc。在检查业务规则并对用户输入执行任何必要的操作之后。。现在,我将在单元测试中模拟我的数据源(一个包含客户对象的列表),并用这个模拟的客户对象的repo为我的服务实例提供数据。。通过这种方式,我可以测试已经编码的服务业务逻辑的正确性。以前我将服务与特定的数据存储(即使用EF DbContext的db)耦合,在单元测试中使用该服务有点困难,因为它已经与db耦合,但我不想仅仅为了执行单元测试而更改和恢复db状态,所以我想用简单的客户对象列表来模拟数据存储。。感谢您的努力,帮助我:)

我不敢相信这两种设置都能按预期工作。两个设置都返回一个
IEnumerable
,但一个表示返回一个
字符串
,另一个表示返回一个
int
。这两个都不是
IEnumerable
。我已经在linq末尾尝试了FirstOrDefault(),这里也不是我的存储库逻辑。。我只是把数据存储模拟成一个列表,里面几乎没有记录。。然后我模仿我的客户服务来进行单元测试。然而,我将改变这种方式,我将添加新用户(为测试做准备),然后我将尝试使用方法mock.Setup(m=>m.GetCustomerById(it.IsAny()).Returns(id=>CustomerRepo.FirstOrDefault(c=>c.id==id));返回是什么意思,我在互联网上读到,返回中的泛型类型实际上是我希望在模拟方法中接收的参数类型,因此我可以根据该参数进行操作,即int是我在模拟对象上调用GetById方法时发送的实际id。@stefo0O0o抱歉,我有点遗漏了语法。
getcustomerbyd
方法的签名是什么?我没有做太多的单元测试和模拟(仍在学习),但是如果我模拟整个服务,那么进行单元测试有什么意义呢。。我是否应该模拟存储库并使用已经编码(或即将实现)的服务来进行测试,以确保我的服务健壮且安全可靠?
mock.Setup(m => m.GetById(42)).Returns<int>(new Customer { Id = 42 });
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
   }
}
[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);