[英]Mocked a method to return true still returns false
I have a controller method like this:我有一个像这样的 controller 方法:
public class ValuesController : Controller
{
private readonly IService fService;
public ValuesController( IService fService)
{
this.fService = fService;
}
public IActionResult InsertDetails( [FromForm]Details details, IFormFile file)
{
bool result = fService.SaveDetails(details, file);
return OK();
}
}
The test case to test this controller is as below:测试此 controller 的测试用例如下:
public class ValuesControllerTests
{
readonly Mock<IService> mockService = new Mock<IService>();
[TestMethod]
public void SaveDetails_Test_Success()
{
var details = GetMockDetails(); // gets the sample DTO values
mockService.Setup(x => x.SaveDetails(details, GetFile())).Returns(true); ---- this is returning false even after mocking the value
var controller = new ValuesController(mockService.Object);
controller.ControllerContext.HttpContext = new DefaultHttpContext();
var res = controller.InsertDetails(details, GetFile()) as OkObjectResult;
Assert.AreEqual("File Details Saved Successfully", res.Value.ToString());
Assert.AreEqual(200, res.StatusCode);
}
IFormFile GetFile()
{
return new FormFile(new MemoryStream(Encoding.UTF8.GetBytes("This is a dummy file")), 0, 0, "Data", "dummy.txt");
}
}
Even though I mocked the method SaveDetails
to return true
, it always returns false
.即使我模拟了
SaveDetails
方法返回true
,它总是返回false
。
Can anyone tell me what am I doing wrong here?谁能告诉我我在这里做错了什么? Many thanks.
非常感谢。
The expectation was setup with a different IFormFile
(reference/instance) than the one that was used when invoking the member under test.期望是使用与调用被测成员时使用的不同的
IFormFile
(引用/实例)设置的。 This causes the mock to return the default value of the invoked member, which is false
since it is a boolean.这会导致模拟返回被调用成员的默认值,这是
false
的,因为它是 boolean。
When GetFile()
is invoked, it returns a new instance every time.调用
GetFile()
时,它每次都会返回一个新实例。
So either use the same instance, like was done with details
所以要么使用相同的实例,就像用
details
做的那样
public void SaveDetails_Test_Success() {
Details details = GetMockDetails();
IFormFile file = GetFile(); //single instance
mockService.Setup(x => x.SaveDetails(details, file)).Returns(true); //used here
ValuesController controller = new ValuesController(mockService.Object);
controller.ControllerContext.HttpContext = new DefaultHttpContext();
var res = controller.InsertDetails(details, file) as OkObjectResult; //and here
Assert.AreEqual("File Details Saved Successfully", res.Value.ToString());
Assert.AreEqual(200, res.StatusCode);
}
Or loosen up the expectation using argument matchers like It.IsAny<>()
或者使用像
It.IsAny<>()
这样的参数匹配器来放松期望
public void SaveDetails_Test_Success() {
Details details = GetMockDetails();
mockService.Setup(x => x.SaveDetails(details, It.IsAny<IFormFile>())).Returns(true); //<-- NOTE
ValuesController controller = new ValuesController(mockService.Object);
controller.ControllerContext.HttpContext = new DefaultHttpContext();
var res = controller.InsertDetails(details, GetFile()) as OkObjectResult;
Assert.AreEqual("File Details Saved Successfully", res.Value.ToString());
Assert.AreEqual(200, res.StatusCode);
}
The problem with your Setup
is that it is too specific.您的
Setup
的问题是它太具体了。
Please bear mind that parameter matching is based on reference check in case of classes.请记住,参数匹配基于类的参考检查。
mockService
.Setup(service => service.SaveDetails(It.IsAny<Details>(), It.IsAny<IFormFile>()))
.Returns(true);
If you would like verify the call then you need to如果您想验证通话,那么您需要
save the result of the GetFile
and then make the assertion:保存
GetFile
的结果,然后进行断言:
public void SaveDetails_Test_Success()
{
//Arrange
var details = GetMockDetails();
var file = GetFile(); //same instance is used everywhere
mockService
.Setup(x => x.SaveDetails(It.IsAny<Details>(), It.IsAny<IFormFile>()))
.Returns(true);
var controller = new ValuesController(mockService.Object);
controller.ControllerContext.HttpContext = new DefaultHttpContext();
//Act
var result = controller.InsertDetails(details, file);
//Assert
var res = Assert.IsAssignableForm<OkObjectResult>(result); //Here we test the assignability as well
Assert.AreEqual("File Details Saved Successfully", res.Value.ToString());
//Assert.AreEqual(200, res.StatusCode); //This assert is unnecessary
mockService
.Verify(x => x.SaveDetails(details, file), Times.Once);
}
Instead of casting the response of the controller's action to OkObjectResult
I would recommend to assert that as well.我建议不要将控制器操作的响应强制转换为
OkObjectResult
。 ( Just like I did in the above test case ) (就像我在上面的测试用例中所做的那样)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.