Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mock.Of async expression #139

Closed
Astrophizz opened this issue Nov 11, 2014 · 5 comments
Closed

Mock.Of async expression #139

Astrophizz opened this issue Nov 11, 2014 · 5 comments

Comments

@Astrophizz
Copy link

Maybe I'm doing it wrong but there doesn't seem to be a way to use the "Linq to Mocks" syntax for mocking async methods. Is it possible? If not, what would it take to make it possible?

@JohanLarsson
Copy link
Contributor

No idea if I read you question right but:

[Test]
public async Task AsyncTest()
{
    var mock = new Mock<IFuu>();
    var propertyChanged = Mock.Of<INotifyPropertyChanged>();
    mock.Setup(x => x.GetAsync()).ReturnsAsync(propertyChanged);
    var actual = await mock.Object.GetAsync();
    Assert.AreSame(propertyChanged, actual);
}

public interface IFuu
{
    Task<INotifyPropertyChanged> GetAsync();
}

@Astrophizz
Copy link
Author

Right, but with synchronous methods you can wrap everything up in Mock.Of<T>() and avoid new Mock<T>(), mock.Setup().Returns(), and mock.Object. Like so:

[Test]
public void Test()
{
    var mock= Mock.Of<INotifyPropertyChanged>(x => x.Get() == propertyChanged);
    var actual = mock.Get();
    Assert.AreSame(propertyChanged, actual);
}

public interface IFuu
{
    INotifyPropertyChanged Get();
}

Mock.Of<T>() can accept a func() as a parameter, but not an async one.

@DaveVdE
Copy link

DaveVdE commented Dec 21, 2016

This worked for me:

var mock = Mock.Of<IService>(service => service.DoAsync() == Task.CompletedTask);

I suppose if you replace Task.CompletedTask with Task.FromResult(something) you can do it with just about everything.

@stakx
Copy link
Contributor

stakx commented Jun 21, 2017

I haven't thought much about this, but my gut feeling is that Mock.Of and async might not fit well together. If it were possible, it would be nice if we could do this:

Mock.Of<IFoo>(async foo => await foo.GetAsync() == 42) 

Unfortunately, today's C# compiler cannot convert async lambdas to expression trees, so that's a major showstopper.

What we're left with is the ability to work directly with Task objects, like @DaveVdE mentioned above. For example:

Mock.Of<IFoo>(foo => foo.GetAsync() == Task.FromResult(42))

The gains here are pretty small. IMHO it is probably better to accept the fact that LINQ to Mocks will likely never be as feature-complete / powerful as the older fluent API (new Mock<>().Setup().Returns()) due to syntactical constraints. By all means, use Mock.Of<> for what it's good at (setting up a bunch of property and return values in an object graph), but do also use the fluent API for more involved scenarios.

@stakx
Copy link
Contributor

stakx commented Jun 22, 2017

Closing this for now, since there's nothing really that can be done. There's simply no way with today's .NET compilers to transform an async lambda to an expression tree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants