【问题标题】:Mocked Async Method in xUnit-Test returns always nullxUnit-Test 中的模拟异步方法总是返回 null
【发布时间】:2020-05-12 14:52:43
【问题描述】:

我有一个 ASP.NET WebAPI 2 项目,我正在尝试使用 xunit 和 moq 添加单元测试。

这是我的控制器中的 Get-Method:

public class SiteController : ApiController
{
    private readonly ISite _siteSrv;

    public SiteController( ISite siteSrv )
    {
        _siteSrv = siteSrv;
    }

    public async Task<IHttpActionResult> Get( int id )
    {
        //reading current user login id and user roles [...]

        // getting data from SiteService, which I try to mock
        var site = await _siteSrv.Get( id, userLoginId.Value, roles );

        //converting it into a model [...]

        return Ok(model);
    }
}

还有我的 SiteService Get 方法:

public async Task<Site> Get( int id, long userLoginId, string[] roles )
{
    //...doing some stuff
    // and returning the data
    return await _context.Sites
        .AsNoTracking()
        .FirstOrDefaultAsync( s => s.SiteId == id );
}

这是我的测试方法:

[Fact]
public async Task Verify_GetId_Method_Returns_OkResult_ForAdmin()
{
    int siteId = 1;
    long userLoginId = 1;
    string role = "Admin";

    // fake site
    var site = new Site()
    {
        SiteId = 1,
        SiteName = "Site1"
    };

    // mocking the SiteService
    var mockSite = new Mock<ISite>();
    // setting up the Get-Method returning the fake site asynchronously
    mockSite.Setup( s => s.Get( siteId, userLoginId, new string[] { role } ) )
        .ReturnsAsync( site );

    // faking HttpContext
    using ( new FakeHttpContext.FakeHttpContext() )
    {
        // current logged in user
        HttpContext.Current.User = CurrentUserTestData.GetAccount( 
            userLoginId, role );

        // the SiteController with the mocked SiteService
        var controller = new SiteController( mockSite.Object );
        // setting Request
        controller.Request = new HttpRequestMessage();
        controller.Request.Properties.Add( 
            HttpPropertyKeys.HttpConfigurationKey,
            new HttpConfiguration() );

        // calling the async Get method of the controller
        var result = await controller.Get( siteId );
        // !! result is always NULL !!

        Assert.NotNull( result ); // FAIL
    }
}

知道我做错了什么吗?

【问题讨论】:

  • 这可能是参数匹配器与您的string[] 角色不匹配,如果可行,请尝试使用It.IsAny&lt;string[],您已经隔离了问题,并且可以在回调中捕获该参数,如果您需要验证是否传递了正确的角色。
  • @JSteward 就是这样。谢谢你。现在我明白了 It.IsAny :) 我用 It.Is 更改了所有 3 个参数并且它有效。昨天我终于写了一个 FakeSiteService 来工作,但这是一个更好的解决方案。您能否将其写为答案,以便我接受。

标签: unit-testing async-await asp.net-web-api2 moq xunit


【解决方案1】:

所以问题是参数匹配器正在查看您的参数并尝试将它们与Setup 中提供的内容相匹配。它通过使用默认相等来做到这一点,这对于数组意味着引用相等。因此,对于您的string[] 角色,您将不会匹配该参数,并且您的Setup 将永远不会匹配,您将得到空结果。更改您的设置以允许任何角色数组将允许匹配器成功。

mockSite.Setup( s => s.Get( siteId, userLoginId, It.IsAny<string[]>() ) )
    .ReturnsAsync( site );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2013-05-03
    • 2016-01-26
    • 2011-09-30
    • 1970-01-01
    • 2020-08-16
    相关资源
    最近更新 更多