I have the following code that compiles.
public class Test
{
[Fact]
public async Task ThisShouldWork()
{
// arrange
var dto = new Dto
{
FName = "John",
LName = "Doe"
};
var mock = Substitute.For<IRepository>();
mock
.SaveAsync(Arg.Any<DomainObject>())
.Returns(args => args[0]);
var service = new BusinessService(mock);
// act
var result = await service.DoSomethingAsync(dto);
// assert
await mock
.Received(1)
.SaveAsync(result);
}
}
public class BusinessService
{
private readonly IRepository _repository;
public BusinessService(IRepository repository)
{
_repository = repository;
}
public async Task<DomainObject> DoSomethingAsync(Dto dto)
{
var domain = new DomainObject
{
FirstName = dto.FName,
LastName = dto.LName
};
return await _repository.SaveAsync(domain);
}
}
public class DomainObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IRepository
{
Task<DomainObject> SaveAsync(DomainObject domain);
}
public class Dto
{
public string FName { get; set; }
public string LName { get; set; }
}
However, if I run the test I get a System.InvalidCastException
.
Unable to cast object of type 'DomainObject' to type 'System.Threading.Tasks.Task`1[DomainObject]'
What am I doing wrong?
Use
.Returns(args => args.Arg<DomainObject>());
or alternatively
.Returns(args => args.ArgAt<DomainObject>(0));
The problem with args[0]
is that it returns object
and therefore the compiler won't take the Returns<T>()
extension method overload on Task<T>
which automatically wraps the result in a task for you.
An explicit cast should also work, but I don't like such code:
.Returns(args => (DomainObject)args[0]);