最小起订量 C# 中的设置和 Returns 是什么?
What is Setup and Returns in MOQ C#?
我阅读了一些关于 Moq
C# 包的教程,但我仍然无法真正理解 Moq
中的 Setup
和 Returns
。
示例,
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
示例 2,
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
)
示例 1
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
设置您的模拟,因此当使用 1 作为参数调用 GetEmployeebyId
时,模拟将 return“JK”。
示例 2
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
当使用 DeskBooking
类型的任何参数调用 Save
方法时,lambda 函数会将参数保存在 savedDeskBooking
变量中。然后您可以测试您是否保存了预期的 DeskBooking
。
TL;DR: Setup
= 何时,Returns
= 什么
无论何时编写单元测试,您都希望确保给定的功能片段按预期工作。但大多数时候,功能取决于一些其他组件/环境/外部源/任何东西。
为了使您的测试具有针对性和可重玩性,我们需要使用测试替身。这些将在测试期间替换您的依赖项。我们可以这样分类测试替身:
- Dummy: returns bogus data
的简单代码
- Fake:一个可行的替代方案,可以走捷径
- 存根:具有预定义数据
的自定义逻辑
- Mock:具有期望的自定义逻辑(交互式存根)
- Shim:自定义逻辑在运行-time(用委托替换静态)
- 间谍:拦截器 记录通话
所以,无论何时你想创建一个模拟,你都必须告诉它在什么情况下组件应该如何表现。换句话说,当使用特定输入调用函数时,什么应该是预期的输出。
如果是 Moq,您可以使用 Setup
来定义时间。和 Returns
指定什么。
这是一个简单的例子。假设您具有以下功能:
private IService service;
string MyMethod()
{
int number = service.GetNextNumber();
if(number % 2 == 0)
{
return "even";
}
else
{
return "odd";
}
}
那么你可以写下面的测试用例:
public void GivenAnEvenNumber_WhenICallMyMethod_ThenItShouldReturnEven
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(2);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("even", result);
}
public void GivenAnOddNumber_WhenICallMyMethod_ThenItShouldReturnOdd
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(1);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("odd", result);
}
因此,如您所见,我们使用 Setup
和 Returns
来指导每个测试用例中的控制流。
你的第二个例子可以被认为是 Spy,因为你在那里记录了后面评估的输入。
我阅读了一些关于 Moq
C# 包的教程,但我仍然无法真正理解 Moq
中的 Setup
和 Returns
。
示例,
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
示例 2,
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
)
示例 1
mock.Setup(p => p.GetEmployeebyId(1)).ReturnsAsync("JK");
设置您的模拟,因此当使用 1 作为参数调用 GetEmployeebyId
时,模拟将 return“JK”。
示例 2
mock.Setup(x => x.Save(It.IsAny<DeskBooking>())).Callback<DeskBooking>(
deskBooking =>
{
savedDeskBooking = deskBooking;
});
当使用 DeskBooking
类型的任何参数调用 Save
方法时,lambda 函数会将参数保存在 savedDeskBooking
变量中。然后您可以测试您是否保存了预期的 DeskBooking
。
TL;DR: Setup
= 何时,Returns
= 什么
无论何时编写单元测试,您都希望确保给定的功能片段按预期工作。但大多数时候,功能取决于一些其他组件/环境/外部源/任何东西。
为了使您的测试具有针对性和可重玩性,我们需要使用测试替身。这些将在测试期间替换您的依赖项。我们可以这样分类测试替身:
- Dummy: returns bogus data 的简单代码
- Fake:一个可行的替代方案,可以走捷径
- 存根:具有预定义数据 的自定义逻辑
- Mock:具有期望的自定义逻辑(交互式存根)
- Shim:自定义逻辑在运行-time(用委托替换静态)
- 间谍:拦截器 记录通话
所以,无论何时你想创建一个模拟,你都必须告诉它在什么情况下组件应该如何表现。换句话说,当使用特定输入调用函数时,什么应该是预期的输出。
如果是 Moq,您可以使用 Setup
来定义时间。和 Returns
指定什么。
这是一个简单的例子。假设您具有以下功能:
private IService service;
string MyMethod()
{
int number = service.GetNextNumber();
if(number % 2 == 0)
{
return "even";
}
else
{
return "odd";
}
}
那么你可以写下面的测试用例:
public void GivenAnEvenNumber_WhenICallMyMethod_ThenItShouldReturnEven
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(2);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("even", result);
}
public void GivenAnOddNumber_WhenICallMyMethod_ThenItShouldReturnOdd
{
//Arrange
var serviceMock = new Mock<IService>();
serviceMock
.Setup(svc => svc.GetNextNumber())
.Returns(1);
...
//Act
var result = SUT.MyMethod();
//Assert
Assert.Equal("odd", result);
}
因此,如您所见,我们使用 Setup
和 Returns
来指导每个测试用例中的控制流。
你的第二个例子可以被认为是 Spy,因为你在那里记录了后面评估的输入。