Domanda

I have some test code asserting duplicate Users cannot be created through my UserRepository.

User.cs:

public class User
{
    public int Id { get; set; }

    public string AccountAlias { get; set; }

    public string DisplayName { get; set; }

    public string Email { get; set; }

    public bool IsActive { get; set; }
}

UserRepository.cs:

public class UserRepository
{
    public virtual async Task<User> CreateAsync(User entity)
    {
        if (entity == null)
        {
            throw new ArgumentNullException("entity");
        }

        if (await GetDuplicateAsync(entity) != null)
        {
            throw new InvalidOperationException("This user already exists");
        }

        return Create(entity);
    }

    public async Task<User> GetDuplicateAsync(User user)
    {
        if (user == null)
        {
            throw new ArgumentNullException("user");
        }

        return await (from u in Users
                      where u.AccountAlias == user.AccountAlias && 
                            u.Id != user.Id && 
                            u.IsActive
                      select u).FirstOrDefaultAsync();
    }
}

UserRepositoryTests.cs:

public sealed class UserRepositoryTests : IDisposable
{
    public UserRepositoryTests()
    {
        UserRepository = new UserRepository(new FooEntities()); // DbContext 
                                                                // from EF
    }

    private UserRepository UserRepository { get; set; }

    [Fact]
    public void DuplicateUserCannotBeCreated()
    {
        var testUser = new User    // This test user already exists in database
        {
            Id = 0,
            AccountAlias = "domain\\foo",
            DisplayName = "Foo",
            Email = "foo@bar.com",
            IsActive = true
        };
        Assert.Throws<InvalidOperationException>(async () => 
            await UserRepository.CreateAsync(testUser));
    }

    public void Dispose()
    {
        if (UserRepository != null)
        {
            UserRepository.Dispose();
        }
    }
}

When I run this unit test, Xunit.Sdk.ThrowsException is thrown (i.e. my InvalidOperationException was not thrown):

Assert.Throws() Failure Expected: System.InvalidOperationException Actual: (No exception was thrown)

From the debugger, GetDuplicateAsync() was evaluated but when the LINQ query was executed, the result was never returned and thus no exception was thrown. Can anyone help?

È stato utile?

Soluzione

xUnit's Assert.Throws (at least on version 1.9.2) is not async-aware. This was fixed in version 2, which now has an Assert.ThrowsAsync method.

So, you can either upgrade to xUnit 2 or create your own method to get it working:

public async static Task<T> ThrowsAsync<T>(Func<Task> testCode) where T : Exception
{
    try
    {
        await testCode();
        Assert.Throws<T>(() => { }); // Use xUnit's default behavior.
    }
    catch (T exception)
    {
        return exception;
    }
    return null;
}

await ThrowsAsync<InvalidOperationException>(async () => await UserRepository.CreateAsync(testUser));

From Haacked's gist.

Altri suggerimenti

XUnit now handle Assert.ThrowAsync by default

This works for me:

Assert.Throws<AbpValidationException>(() => _personAppService.CreatePersonAsync(new CreatePersonInput { Name = null }));

Just don't use async/await.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top