使用Moq设置Mock存储库

时间:2019-08-04 12:43:12

标签: c# unit-testing asp.net-core moq xunit

我正在使用xUnit和Moq进行单元测试控制器逻辑。我正在尝试使用一个Mock存储库对象,该对象将使测试用例能够通过。但是,在我的设置中,由于Mock存储库返回null而不是TweetDay对象,导致测试失败。

我正在测试TweetsController:

public class TweetsController : ControllerBase
{
    private readonly ITweetDayRepository _tweetDayRepository;

    public TweetsController(ITweetDayRepository tweetDayRepository)
    {
        //Implementation here
    }

    public async Task<IActionResult> GetTweetDay()
    {
            var tweet = await _tweetDayRepository.GetTweetOfTheDayAsync(_systemClock.GetToday);

            if (tweet == null)
            {
                _logger.LogError(LoggingEvents.GetItemNotFound, "An error occurred getting tweet with date: {Date}", _systemClock.GetToday);
                return BadRequest();
            }

            return Ok(tweet);
        }
        catch (Exception ex)
        {
            _logger.LogError(LoggingEvents.GetItemNotFound, ex, "An error occurred getting tweet with date: {Date}", _systemClock.GetToday);
            return BadRequest();
        }
    }
}

下面是我的测试用例:

public class TweetsControllerTests
{
    private Mock<IMemoryCache> _cache;
    private readonly Mock<IMapper> _mapper;
    private readonly Mock<ILogger<TweetsController>> _logger;
    private readonly Mock<ISystemClockService> _systemClock;
    //private readonly ITweetDayRepository _tweetDayRepository;

    public TweetsControllerTests()
    {
        _cache = new Mock<IMemoryCache>();
        _mapper = new Mock<IMapper>();
        _systemClock = new Mock<ISystemClockService>();
        _logger = new Mock<ILogger<TweetsController>>();
    }

    [Fact]
    public async Task GetTweetDay_ReturnsOkResult_WithATweetObject()
    {
        // Arrange
        var mockRepo = new Mock<ITweetDayRepository>();
        mockRepo.Setup(repo => repo.GetTweetOfTheDayAsync(DateTime.Today))
            .ReturnsAsync(GetTestTweet());

        var controller = new TweetsController(mockRepo.Object, _cache.Object, _logger.Object,
                                                 _systemClock.Object, _mapper.Object);

        // Act
        var result = await controller.GetTweetDay();

        // Assert
        var okResult = Assert.IsType<OkResult>(result);
    }

    private TweetDay GetTestTweet()
    {
        var tweet = new TweetDay()
        {
            Bird = new Bird(),
            BirdId = 0,
            CreationDate = new DateTime(2016, 7, 2),
            DisplayDay = new DateTime(2016, 7, 2),
            LastUpdateDate = new DateTime(2016, 7, 2),
            TweetDayId = 0
        };

        return tweet;
    }
}

在我的设置下,我希望Mock存储库返回初始化为的TweetDay对象

mockRepo.Setup(repo => repo.GetTweetOfTheDayAsync(DateTime.Today))
    .ReturnsAsync(GetTestTweet());

我无法找出问题的确切根源。

我是否正确设置了Mock存储库?还是其他地方有问题?

1 个答案:

答案 0 :(得分:0)

基于显示的设置,您中的一个注入了模拟依赖项(我怀疑系统时钟)

 var tweet = await _tweetDayRepository.GetTweetOfTheDayAsync(_systemClock.GetToday);

表现不正常,导致硬编码的DateTime.Today期望值不匹配,因此返回null或与匹配器中使用的默认值不同的默认值。

您可以通过放松目标模拟中的预期匹配来解决此问题

mockRepo
.Setup(repo => repo.GetTweetOfTheDayAsync(It.IsAny<DateTime>()))
.ReturnsAsync(GetTestTweet());