使用 NUnit 和 Moq 返回 Null 的单元测试异步控制器方法
Unit Testing Async Controller Method Returning Null with NUnit and Moq
我有一个 .NET Core API Framework 6.0,我正在使用 NUnit Framework 编写测试异步控制器方法我得到控制器身份验证方法返回的空值。当我从 Postman 打一个类似的电话时,有回应。我假设我的最小起订量遗漏了一些东西,但我已经按照文档进行操作,但无法找出问题所在。
//User Controller
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate([FromBody] UserRequest userRequest)
{
try
{
var response = await _userService.Authenticate(userRequest); //Authenticate method is not being called, response is NULL here
return Ok(new ApiResponse<UserResponse>().Success(response));
}
catch (Exception ex)
{
return betServerError(ex);
}
}
Authenticate方法如下,第1行断点未命中
public async Task<UserResponse> Authenticate(UserRequest userRequest)
{
var user = _context.Users.Where(x => x.Email == userRequest.Email).FirstOrDefault(); //Breakpoint here is not being hit
bool valid = false;
if (user == null)
throw new HttpException(HttpStatusCode.Unauthorized, "Username or password incorrect");
//Other code ......
return new UserResponse
{
Id = user.Id,
Email = user.Email,
Token = tokenString
};
}
UserTest.cs 看起来如下:
Mock<IUserService> UserServiceMock = new Mock<IUserService>();
[SetUp]
public void Setup()
{
}
[Test]
public async Task should_Login()
{
//Arrange
var user = new UserResponse
{
Id = 1,
Email = "username@gmail.com",
Token = "TEST_TOKEN"
};
UserServiceMock.Setup(x => x.Authenticate(new UserRequest { Email = "username@gmail.com", Password = "password" }))
.Returns(Task.Run(() => user));
var UserController = new UserController(UserServiceMock.Object);
//Act
var result = await UserController.Authenticate(new UserRequest { Email = "username@gmail.com", Password = "password1" }); //result here doesnot contain the response I expect, it has a null object
//Assert
Assert.IsNotNull(result);
Assert.AreEqual(HttpStatusCode.OK, GetHttpStatusCode(result));
}
您传递给 Authenticate
的 UserRequest
实例与您设置模拟所期望的实例不同。因此,由于输入不匹配,模拟不会执行,默认模拟行为将接管。
要么删除模拟条件(即使用 It.IsAny<UserRequest>()
),要么将相同的实例传递给模拟和控制器方法。
我有一个 .NET Core API Framework 6.0,我正在使用 NUnit Framework 编写测试异步控制器方法我得到控制器身份验证方法返回的空值。当我从 Postman 打一个类似的电话时,有回应。我假设我的最小起订量遗漏了一些东西,但我已经按照文档进行操作,但无法找出问题所在。
//User Controller
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
[AllowAnonymous]
[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate([FromBody] UserRequest userRequest)
{
try
{
var response = await _userService.Authenticate(userRequest); //Authenticate method is not being called, response is NULL here
return Ok(new ApiResponse<UserResponse>().Success(response));
}
catch (Exception ex)
{
return betServerError(ex);
}
}
Authenticate方法如下,第1行断点未命中
public async Task<UserResponse> Authenticate(UserRequest userRequest)
{
var user = _context.Users.Where(x => x.Email == userRequest.Email).FirstOrDefault(); //Breakpoint here is not being hit
bool valid = false;
if (user == null)
throw new HttpException(HttpStatusCode.Unauthorized, "Username or password incorrect");
//Other code ......
return new UserResponse
{
Id = user.Id,
Email = user.Email,
Token = tokenString
};
}
UserTest.cs 看起来如下:
Mock<IUserService> UserServiceMock = new Mock<IUserService>();
[SetUp]
public void Setup()
{
}
[Test]
public async Task should_Login()
{
//Arrange
var user = new UserResponse
{
Id = 1,
Email = "username@gmail.com",
Token = "TEST_TOKEN"
};
UserServiceMock.Setup(x => x.Authenticate(new UserRequest { Email = "username@gmail.com", Password = "password" }))
.Returns(Task.Run(() => user));
var UserController = new UserController(UserServiceMock.Object);
//Act
var result = await UserController.Authenticate(new UserRequest { Email = "username@gmail.com", Password = "password1" }); //result here doesnot contain the response I expect, it has a null object
//Assert
Assert.IsNotNull(result);
Assert.AreEqual(HttpStatusCode.OK, GetHttpStatusCode(result));
}
您传递给 Authenticate
的 UserRequest
实例与您设置模拟所期望的实例不同。因此,由于输入不匹配,模拟不会执行,默认模拟行为将接管。
要么删除模拟条件(即使用 It.IsAny<UserRequest>()
),要么将相同的实例传递给模拟和控制器方法。