ibram
ibram

Reputation: 4569

Mocked Async Method in xUnit-Test returns always null

I have a ASP.NET WebAPI 2 project and I am trying to add unit-testing with xunit and moq.

This is my Get-Method in my Controller:

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);
    }
}

And my SiteService Get method:

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 );
}

This is my Test-Method:

[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
    }
}

Any idea what I am doing wrong?

Upvotes: 2

Views: 943

Answers (1)

JSteward
JSteward

Reputation: 7091

So the issue is that the argument matcher is looking at your arguments and trying to match them to what was provided in the Setup. It does this by using the default equality which for arrays means reference equality. So for your string[] of roles you won't match that argument and your Setup will never be matched and you'll get a null result. Changing your setup to allow any array of roles will allow the matcher to succeed.

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

Upvotes: 1

Related Questions