即使在使用 Moq 设置时发送正确数量的参数,也会获得 System.ArgumentException
Getting System.ArgumentException even while sending the right number of parameters while using Moq setup
在对我的 ASP.NET 网络 api 控制器进行单元测试时,对于我的一个 post 请求,我在 repo 函数中发送了两个参数,像往常一样我在模拟存储库设置,但即使我发送两个参数,我也会收到参数异常。
回购代码-
public async Task<TblUser> Register(TblUser user, string password)
{
byte[] passwordHash, passwordSalt;
CreatePasswordHash(password, out passwordHash, out passwordSalt);
user.APasswordHash = passwordHash;
user.APasswordSalt = passwordSalt;
await _context.TblUser.AddAsync(user);
await _context.SaveChangesAsync();
return user;
}
控制器代码-
[HttpPost("register")]
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{
userForRegisterDto.AUsername = userForRegisterDto.AUsername.ToLower();
if (await _repo.UserExists(userForRegisterDto.AUsername))
return BadRequest("username already exists");
if(!ModelState.IsValid || userForRegisterDto.AUsername == null || userForRegisterDto.Password == null || userForRegisterDto.AEmail ==null || userForRegisterDto.Aname ==null)
{
return BadRequest("invalid user");
}
var userToCreate = _mapper.Map<TblUser>(userForRegisterDto);
var createdUser = await _repo.Register(userToCreate, userForRegisterDto.Password);
var userToReturn = _mapper.Map<UserForDetailedDto>(createdUser);
return CreatedAtRoute("GetUser", new
{
controller = "Users",
id = createdUser.ACustomerId
}, userToReturn
);
}
控制器测试代码-
[Test]
public async Task GivenAValidUser_WhenIRegisterANewUser_ThenItReturnsOkWithResponse()
{
_mockAuthRepository = new Mock<IAuthRepository>();
_mockAuthMapper = new Mock<IMapper>();
_mockConfig = new Mock<IConfiguration>();
UserForRegisterDto expectedUser = new UserForRegisterDto
{
Aname = "Luffy",
AUsername = "luffy",
AEmail = "luffy@gmail.com",
Password = "password",
ADob = new DateTime(2000, 12, 12)
};
_mockAuthMapper.Setup(mapper => mapper.Map<TblUser>(It.IsAny<UserForRegisterDto>()))
.Returns(new TblUser());
_mockAuthMapper.Setup(mapper => mapper.Map<UserForDetailedDto>(It.IsAny<TblUser>()))
.Returns(new UserForDetailedDto());
_mockAuthRepository.Setup(repo => repo.Register(It.IsAny<TblUser>(), It.IsAny<string>()))
.ReturnsAsync((TblUser user) => user);
_authController = new AuthController(_mockAuthRepository.Object,_mockConfig.Object, _mockAuthMapper.Object);
var tblUser = await _authController.Register(expectedUser);
var okResult = tblUser as OkObjectResult;
Assert.AreEqual(200, okResult.StatusCode);
Assert.NotNull(okResult);
Assert.IsAssignableFrom<OkObjectResult>(tblUser);
var result = ((OkObjectResult)tblUser).Value;
Assert.NotNull(result);
Assert.AreEqual(expectedUser, result);
Assert.IsAssignableFrom<TblUser>(result);
}
异常由行抛出-
_mockAuthRepository.Setup(repo => repo.Register(It.IsAny<TblUser>(), It.IsAny<string>()))
.ReturnsAsync((TblUser user) => user);
如您所见,在设置模拟存储库时,我发送了两个参数,但出现了错误-
Message:
System.ArgumentException : Invalid callback. Setup on method with 2 parameter(s) cannot invoke callback with different number of parameters (1).
堆栈跟踪:
<>c__DisplayClass22_0
<SetReturnComputedValueBehavior>g__ValidateCallback|4(Delegate callback)
MethodCall.SetReturnComputedValueBehavior(Delegate valueFactory)
NonVoidSetupPhrase`2.Returns[T1](Func`2 valueExpression)
GeneratedReturnsExtensions.ReturnsAsync[T,TMock,TResult]
(IReturns`2 mock, Func`2 valueFunction) AuthControllerTests.GivenAValidUser_WhenIRegisterANewUser_ThenItReturnsOkWithResponse() line 43
GenericAdapter`1.GetResult()
AsyncToSyncAdapter.Await(Func`1 invoke)
TestMethodCommand.RunTestMethod(TestExecutionContext context)
TestMethodCommand.Execute(TestExecutionContext context)
SimpleWorkItem.PerformWork()
我是单元测试的新手,但到目前为止,我对 GET 和 POST 请求的单元测试一直以这种方式运行良好。这是我在内部调用的哈希函数的问题吗?
正在运行的控制器代码-
[允许匿名]
[HttpPost()]
public 异步任务 AddMovie(MovieForDetailedDto movieForDetailedDto)
{
如果(等待_repo.MovieExists(movieForDetailedDto.ATitle))
return BadRequest("电影已经存在");
else if(!ModelState.IsValid || movieForDetailedDto.ATitle == null || movieForDetailedDto.APrice == null || movieForDetailedDto.AMovieDescription ==null)
{
return BadRequest("movie details not valid");
}
var movieToCreate = _mapper.Map<TblMovie>(movieForDetailedDto);
var createdMovie = await _repo.AddMovie(movieToCreate);
return Ok(createdMovie);
}
适用于上述控制器的测试-
[Test]
public async Task GivenAValidMovie_WhenIPostANewMovie_ThenItReturnsOkWithResponse()
{
_mockMovieRepository = new Mock<IMovieRepository>();
_mockMovieMapper = new Mock<IMapper>();
TblMovie expectedMovie = new TblMovie
{
AMovieId = 55,
ATitle = "redemption",
AMovieDescription = "An action comedy adventure about brilliant robotics prodigy Hiro Hamada, who finds himself in the grips of a criminal plot that threatens to destroy the fast-paced, high-tech city of San Fransokyo. With the help of his closest companion-a robot named Baymax-Hiro joins forces with a reluctant team of first-time crime fighters on a mission to save their city.",
ADuration = "105 min",
APrice = "10",
APurchasePrice = "25",
ARating = 5,
AImageLink = "http://upload.wikimedia.org/wikipedia/en/4/4b/Big_Hero_6_%28film%29_poster.jpg",
ATrailerLink = "//www.youtube.com/embed/z3biFxZIJOQ",
AGenre = "Comedy",
AWideImage = "https://github.com/tushar23091998/MovieRentalApp-FrontEnd/blob/master/src/app/images/bighero6.jpg?raw=true"
};
_mockMovieMapper.Setup(mapper => mapper.Map<TblMovie>(It.IsAny<MovieForDetailedDto>()))
.Returns(expectedMovie);
_mockMovieRepository.Setup(repo => repo.AddMovie(It.IsAny<TblMovie>()))
.ReturnsAsync((TblMovie movie) => movie);
_moviesController = new MoviesController(_mockMovieRepository.Object, _mockMovieMapper.Object);
var tblMovie = await _moviesController.AddMovie(new MovieForDetailedDto
{
AMovieId = 55,
ATitle = "redemption",
AMovieDescription = "An action comedy adventure about brilliant robotics prodigy Hiro Hamada, who finds himself in the grips of a criminal plot that threatens to destroy the fast-paced, high-tech city of San Fransokyo. With the help of his closest companion-a robot named Baymax-Hiro joins forces with a reluctant team of first-time crime fighters on a mission to save their city.",
ADuration = "105 min",
APrice = "10",
APurchasePrice = "25",
ARating = 5,
AImageLink = "http://upload.wikimedia.org/wikipedia/en/4/4b/Big_Hero_6_%28film%29_poster.jpg",
ATrailerLink = "//www.youtube.com/embed/z3biFxZIJOQ",
AGenre = "Comedy",
AWideImage = "https://github.com/tushar23091998/MovieRentalApp-FrontEnd/blob/master/src/app/images/bighero6.jpg?raw=true"
});
var okResult = tblMovie as OkObjectResult;
Assert.AreEqual(200, okResult.StatusCode);
Assert.NotNull(okResult);
Assert.IsAssignableFrom<OkObjectResult>(tblMovie);
var result = ((OkObjectResult)tblMovie).Value;
Assert.NotNull(result);
Assert.AreEqual(expectedMovie,result);
Assert.IsAssignableFrom<TblMovie>(result);
}
所以我以前只接受一个参数的 repo 函数工作正常。
感谢您的宝贵时间。如果答案太明显,我们深表歉意。
.ReturnsAsync((TblUser user) =>
只有一个参数。这应该是
.ReturnsAsync((TblUser user, string password) =>
在对我的 ASP.NET 网络 api 控制器进行单元测试时,对于我的一个 post 请求,我在 repo 函数中发送了两个参数,像往常一样我在模拟存储库设置,但即使我发送两个参数,我也会收到参数异常。
回购代码-
public async Task<TblUser> Register(TblUser user, string password)
{
byte[] passwordHash, passwordSalt;
CreatePasswordHash(password, out passwordHash, out passwordSalt);
user.APasswordHash = passwordHash;
user.APasswordSalt = passwordSalt;
await _context.TblUser.AddAsync(user);
await _context.SaveChangesAsync();
return user;
}
控制器代码-
[HttpPost("register")]
public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto)
{
userForRegisterDto.AUsername = userForRegisterDto.AUsername.ToLower();
if (await _repo.UserExists(userForRegisterDto.AUsername))
return BadRequest("username already exists");
if(!ModelState.IsValid || userForRegisterDto.AUsername == null || userForRegisterDto.Password == null || userForRegisterDto.AEmail ==null || userForRegisterDto.Aname ==null)
{
return BadRequest("invalid user");
}
var userToCreate = _mapper.Map<TblUser>(userForRegisterDto);
var createdUser = await _repo.Register(userToCreate, userForRegisterDto.Password);
var userToReturn = _mapper.Map<UserForDetailedDto>(createdUser);
return CreatedAtRoute("GetUser", new
{
controller = "Users",
id = createdUser.ACustomerId
}, userToReturn
);
}
控制器测试代码-
[Test]
public async Task GivenAValidUser_WhenIRegisterANewUser_ThenItReturnsOkWithResponse()
{
_mockAuthRepository = new Mock<IAuthRepository>();
_mockAuthMapper = new Mock<IMapper>();
_mockConfig = new Mock<IConfiguration>();
UserForRegisterDto expectedUser = new UserForRegisterDto
{
Aname = "Luffy",
AUsername = "luffy",
AEmail = "luffy@gmail.com",
Password = "password",
ADob = new DateTime(2000, 12, 12)
};
_mockAuthMapper.Setup(mapper => mapper.Map<TblUser>(It.IsAny<UserForRegisterDto>()))
.Returns(new TblUser());
_mockAuthMapper.Setup(mapper => mapper.Map<UserForDetailedDto>(It.IsAny<TblUser>()))
.Returns(new UserForDetailedDto());
_mockAuthRepository.Setup(repo => repo.Register(It.IsAny<TblUser>(), It.IsAny<string>()))
.ReturnsAsync((TblUser user) => user);
_authController = new AuthController(_mockAuthRepository.Object,_mockConfig.Object, _mockAuthMapper.Object);
var tblUser = await _authController.Register(expectedUser);
var okResult = tblUser as OkObjectResult;
Assert.AreEqual(200, okResult.StatusCode);
Assert.NotNull(okResult);
Assert.IsAssignableFrom<OkObjectResult>(tblUser);
var result = ((OkObjectResult)tblUser).Value;
Assert.NotNull(result);
Assert.AreEqual(expectedUser, result);
Assert.IsAssignableFrom<TblUser>(result);
}
异常由行抛出-
_mockAuthRepository.Setup(repo => repo.Register(It.IsAny<TblUser>(), It.IsAny<string>()))
.ReturnsAsync((TblUser user) => user);
如您所见,在设置模拟存储库时,我发送了两个参数,但出现了错误-
Message:
System.ArgumentException : Invalid callback. Setup on method with 2 parameter(s) cannot invoke callback with different number of parameters (1).
堆栈跟踪:
<>c__DisplayClass22_0
<SetReturnComputedValueBehavior>g__ValidateCallback|4(Delegate callback)
MethodCall.SetReturnComputedValueBehavior(Delegate valueFactory)
NonVoidSetupPhrase`2.Returns[T1](Func`2 valueExpression)
GeneratedReturnsExtensions.ReturnsAsync[T,TMock,TResult]
(IReturns`2 mock, Func`2 valueFunction) AuthControllerTests.GivenAValidUser_WhenIRegisterANewUser_ThenItReturnsOkWithResponse() line 43
GenericAdapter`1.GetResult()
AsyncToSyncAdapter.Await(Func`1 invoke)
TestMethodCommand.RunTestMethod(TestExecutionContext context)
TestMethodCommand.Execute(TestExecutionContext context)
SimpleWorkItem.PerformWork()
我是单元测试的新手,但到目前为止,我对 GET 和 POST 请求的单元测试一直以这种方式运行良好。这是我在内部调用的哈希函数的问题吗?
正在运行的控制器代码- [允许匿名] [HttpPost()] public 异步任务 AddMovie(MovieForDetailedDto movieForDetailedDto) { 如果(等待_repo.MovieExists(movieForDetailedDto.ATitle)) return BadRequest("电影已经存在");
else if(!ModelState.IsValid || movieForDetailedDto.ATitle == null || movieForDetailedDto.APrice == null || movieForDetailedDto.AMovieDescription ==null)
{
return BadRequest("movie details not valid");
}
var movieToCreate = _mapper.Map<TblMovie>(movieForDetailedDto);
var createdMovie = await _repo.AddMovie(movieToCreate);
return Ok(createdMovie);
}
适用于上述控制器的测试-
[Test]
public async Task GivenAValidMovie_WhenIPostANewMovie_ThenItReturnsOkWithResponse()
{
_mockMovieRepository = new Mock<IMovieRepository>();
_mockMovieMapper = new Mock<IMapper>();
TblMovie expectedMovie = new TblMovie
{
AMovieId = 55,
ATitle = "redemption",
AMovieDescription = "An action comedy adventure about brilliant robotics prodigy Hiro Hamada, who finds himself in the grips of a criminal plot that threatens to destroy the fast-paced, high-tech city of San Fransokyo. With the help of his closest companion-a robot named Baymax-Hiro joins forces with a reluctant team of first-time crime fighters on a mission to save their city.",
ADuration = "105 min",
APrice = "10",
APurchasePrice = "25",
ARating = 5,
AImageLink = "http://upload.wikimedia.org/wikipedia/en/4/4b/Big_Hero_6_%28film%29_poster.jpg",
ATrailerLink = "//www.youtube.com/embed/z3biFxZIJOQ",
AGenre = "Comedy",
AWideImage = "https://github.com/tushar23091998/MovieRentalApp-FrontEnd/blob/master/src/app/images/bighero6.jpg?raw=true"
};
_mockMovieMapper.Setup(mapper => mapper.Map<TblMovie>(It.IsAny<MovieForDetailedDto>()))
.Returns(expectedMovie);
_mockMovieRepository.Setup(repo => repo.AddMovie(It.IsAny<TblMovie>()))
.ReturnsAsync((TblMovie movie) => movie);
_moviesController = new MoviesController(_mockMovieRepository.Object, _mockMovieMapper.Object);
var tblMovie = await _moviesController.AddMovie(new MovieForDetailedDto
{
AMovieId = 55,
ATitle = "redemption",
AMovieDescription = "An action comedy adventure about brilliant robotics prodigy Hiro Hamada, who finds himself in the grips of a criminal plot that threatens to destroy the fast-paced, high-tech city of San Fransokyo. With the help of his closest companion-a robot named Baymax-Hiro joins forces with a reluctant team of first-time crime fighters on a mission to save their city.",
ADuration = "105 min",
APrice = "10",
APurchasePrice = "25",
ARating = 5,
AImageLink = "http://upload.wikimedia.org/wikipedia/en/4/4b/Big_Hero_6_%28film%29_poster.jpg",
ATrailerLink = "//www.youtube.com/embed/z3biFxZIJOQ",
AGenre = "Comedy",
AWideImage = "https://github.com/tushar23091998/MovieRentalApp-FrontEnd/blob/master/src/app/images/bighero6.jpg?raw=true"
});
var okResult = tblMovie as OkObjectResult;
Assert.AreEqual(200, okResult.StatusCode);
Assert.NotNull(okResult);
Assert.IsAssignableFrom<OkObjectResult>(tblMovie);
var result = ((OkObjectResult)tblMovie).Value;
Assert.NotNull(result);
Assert.AreEqual(expectedMovie,result);
Assert.IsAssignableFrom<TblMovie>(result);
}
所以我以前只接受一个参数的 repo 函数工作正常。
感谢您的宝贵时间。如果答案太明显,我们深表歉意。
.ReturnsAsync((TblUser user) =>
只有一个参数。这应该是
.ReturnsAsync((TblUser user, string password) =>