即使在使用Moq设置发送正确数量的参数时也获得System.ArgumentException

问题描述

在对我的ASP.NET Web api控制器进行单元测试时,对于我的一个发布请求,我正在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 = "[email protected]",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请求的单元测试一直很好。这是我在内部调用的哈希函数吗?

正在运行的控制器代码- [AllowAnonymous] [HttpPost()] 公共异步任务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,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函数工作正常。

感谢您的宝贵时间。如果答案太明显,则表示歉意。

解决方法

<div id="page">
  <div class="container">This is a test</div>
</div>

只有一个参数。应该是

.ReturnsAsync((TblUser user) =>