How do I set up a verifiable expectation on a mocked async method? [duplicate] - async-await

This question already has answers here:
How can I tell Moq to return a Task?
(5 answers)
Closed 6 years ago.
I'm trying to use Moq to test integration between a WebAPI controller and a Redis database, using the StackExchange.Redis client, and cannot work out how to set up a verifiable expectation on a mocked async method that includes a callback or some other assertion behaviour.
Ordinarily, I'd use the following syntax:
const string KEY = "some_key";
var db = new Mock<IDatabase>();
db.Setup(d => d.HashSetAsync(KEY, It.IsAny<HashEntry[]>(),It.IsAny<CommandFlags>()))
.Callback<RedisKey,HashEntry[],CommandFlags>((key, hash, flags) => {
hash.ShouldContain(entry => entry.Name == "customerid");
hash.ShouldContain(entry => entry.Name == "quotenumber");
})
.Verifiable();
But this is giving me:
'Moq.Language.Flow.IReturnsThrows<StackExchange.Redis.IDatabase,System.Threading.Tasks.Task>' does not contain a definition for 'Verifiable' and no extension method 'Verifiable' accepting a first argument of type 'Moq.Language.Flow.IReturnsThrows' could be found (are you missing a using directive or an assembly reference?)
If I change db.HashSetAsync to db.HashSet in the Setup invocation, it works as expected. It appears that the setting a Callback on a regular method returns an ICallbackResult but setting a callback on an async method invocation returns an IReturnsThrows - and I'm not sure how you mark one of those as verifiable. Any ideas?

For async methods you need to return a completed Task from the setup before using a callback
have a look here:
Using Moq to mock an asynchronous method for a unit test
You're creating a task but never starting it, so it's never
completing. However, don't just start the task - instead, change to
using Task.FromResult<TResult> which will give you a task which has
already completed:
this works
const string KEY = "some_key";
var db = new Mock<IDatabase>();
db.Setup(d => d.HashSetAsync(KEY, It.IsAny<HashEntry[]>(), It.IsAny<CommandFlags>()))
.Returns(Task.FromResult<object>(null))
.Callback<RedisKey, HashEntry[], CommandFlags>((key, hash, flags) => {
hash.ShouldContain(entry => entry.Name == "customerid");
hash.ShouldContain(entry => entry.Name == "quotenumber");
})
.Verifiable();

Related

How to represent method calls ReScript 9.1.2

ReScript 9.1.2 made the original #meth semantics inaccessible they said to use #send external instead to represent method calls
My questions are:
can #send external be inside a type?
and is this a correct way to use it knowing that it generates the same javascript code?
Using #meth:
#meth
"createElement": string => Web_node.t,
let createElement = typ => document["createElement"](typ
Using #send external:
#send external
createElement: (t,string) => Web_node.t="createElement"
let createElement = typ => createElement(document, typ)
I don't know what you mean by "inside a type", but yes, that is how you represent a method call. You can verify this by looking at the generated JavaScript. An easy way to do this is by creating an example in the rescript playground, which will show that it generates this:
function createElement(typ) {
return document.createElement(typ);
}
Another handy resource is the rescript bindings cookbook.

Optional arguments for higher-order functions

I try to write a binding for socket.io.
I am having trouble with a function (next() in my example code at the bottom), that either takes no argument or a error object (Js.Exn.raiseError("ERROR!")).
I can't find a way to define a function signature that can take both types of argument as the first value.
I am not even sure, if what I am asking for is possible in rescript, any help to solve that problem in the proper rescript way, would be appreciated.
My current implementation looks like this:
type server
type socket
type next = (. unit) => unit
#new #module("socket.io") external socketIO: unit => server = "Server"
#send external use: (server, (socket, next) => unit) => unit = "use"
#send external listen: (server, int) => unit = "listen"
#send external on: (server, #string [ #connection(socket => unit) ] ) => unit = "on"
let io = socketIO()
io->use((socket, next) => {
Js.log("FIRST")
next(.)
})
io->use((socket, next) => {
Js.log("SECOND")
next(.)
})
io->on(#connection(socket =>
Js.log("CONNECT")
))
io->listen(3000)
It's not possible in general to have a function with a variable number of arguments, but it is possible to pass either undefined or a value, which in most cases will be equivalent.
One way to do so is to simply use the option type. If we re-define next as
type next = (. option<int>) => unit
we can use it like this
io->use((_socket, next) => {
next(. None)
next(. Some(42))
})
which will generate the following JavaScript:
io.use(function (_socket, next) {
next(undefined);
return next(42);
});
Another option could be to use optional arguments, but this doesn't seem to work with uncurrying, and recently there's been bugs with currying that the compiler author seems to have no interest in fixing, so it might not work there either, but it might be worth a shot:
type next = (~error: int=?, unit) => unit
...
io->use((_socket, next) => {
next(())
next(~error=42, ())
})
Lastly, there already exists some bindings for socket.io (bs-socket.io). These also don't handle this case unfortunately, but it might save you from re-inventing some wheels at least.

Does CreateFromObservable works asynchrony?

I'm trying use ReactiveUI 7.4 in WPF project, and I think it's great framework. But it causes great difficulties in studying the absence, or the outdated documentation.
In doc https://docs.reactiveui.net/en/user-guide/commands/asynchronous-synchronous.html says so CreateFromObservable is asynchrony, but in my example it's run syncronly.
RefreshList = ReactiveCommand.CreateFromObservable<ReactiveList<ClientDto>>(
() => Observable
.Return(_clientsService.GetClientsList())
and latter
_isBusy = this.WhenAnyObservable(x => x.RefreshList.IsExecuting)
.ToProperty(this, vm => vm.IsBusy);
when i do InvokeCommand method runs syncronly, and IsExecuting observe only after GetClientsList() completed (change to false and after to true). But variand with task works:
RefreshList = ReactiveCommand.CreateFromTask(async _ =>
{
return await Task.Run(() => _clientsService.GetClientsList());
}
);
Is it bug? Or changes in framework?
PS I also trying plays with SubscribeOn and ObservableOn but nothing helps (((.
Observable.Return() does it's work on the current thread, which means it's blocking. In your case the current thread is the UI thread.
You can specify a scheduler, but that only affects where the value is returned, not where it's produced.
I've written about Observable.Return() and how it behaves in this blog post.
It looks like _clientsService.GetClientsList() is implemented synchronously. To make it asynchronous you can move the work to the task pool. You've already done this by running it in a Task. It's also possible to use `Observable.Start()ยด:
RefreshList = ReactiveCommand.CreateFromObservable<ReactiveList<ClientDto>>(
() => Observable
.Start(_clientsService.GetClientsList(), RxApp.TaskpoolScheduler);

Binding to ReactiveCommand.IsExecuting

I'm would like to know the recommended way to bind to ReactiveCommand's IsExecuting.
The problem is the initial command execution (started at the end of the constructor) is not updating the WPF control using IsLoading as a binding, although subsequent calls work as expected.
Update 2 Add test binding code
This shows the adorner content when IsLoading is true
<ac:AdornedControl IsAdornerVisible="{Binding IsLoading}">
<ac:AdornedControl.AdornerContent>
<controls1:LoadingAdornerContent/>
</ac:AdornedControl.AdornerContent>
<fluent:ComboBox
ItemsSource="{Binding Content, Mode=OneWay}"
DisplayMemberPath="Name"
SelectedValuePath="ContentId"
SelectedValue="{Binding SelectedContentId}"
IsSynchronizedWithCurrentItem="True"
/>
</ac:AdornedControl>
Update
I found this:
https://github.com/reactiveui/rxui-design-guidelines
and figured I should be able to do something like:
this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
.ToProperty(this, x => x.IsLoading);
but it gives the compilation error:
The type arguments for method
'ReactiveUI.OAPHCreationHelperMixin.ToProperty<
TObj,TRet>(System.IObservable< TRet>, TObj,
System.Linq.Expressions.Expression< System.Func< TObj,TRet>>, TRet,
System.Reactive.Concurrency.IScheduler)' cannot be inferred from the
usage. Try specifying the type arguments explicitly.
I also tried:
this._isLoading = this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
.ToProperty<TheViewModel, bool>(this, x => x.IsLoading);
but get the compilation error:
'System.IObservable< System.IObservable< bool >>' does not contain a
definition for 'ToProperty' and the best extension method overload
'ReactiveUI.OAPHCreationHelperMixin.ToProperty<
TObj,TRet>(System.IObservable< TRet>, TObj,
System.Linq.Expressions.Expression< System.Func< TObj,TRet>>, TRet,
System.Reactive.Concurrency.IScheduler)' has some invalid arguments
and
Instance argument: cannot convert from
'System.IObservable>' to
'System.IObservable'
Original Below
The code listed at the end of my post works for the initial bind by accessing the IsLoading property and it sounds like that kicks off a subscription. But from further reading it seems I should be using WhenAny and I can't seem to figure out what has been put in front of my nose:
ToProperty and BindTo - Get initial value without Subscribing
Adding:
this.WhenAnyValue(x => x.LoadCommand.IsExecuting);
also works, but is there a better way?
I was thinking removing the ObservableAsPropertyHelper as it doesn't seem to be doing much for me and making IsLoading a normal property like:
private bool _isLoading;
public bool IsLoading
{
get { return _isLoading; }
set { this.RaiseAndSetIfChanged(ref _isLoading, value); }
}
And doing something like the following, but it doesn't compile because it is trying to assign a IObservable< bool> to a bool:
this.WhenAnyValue(x => x.LoadCommand.IsExecuting)
.Subscribe(x => IsLoading = x);
Current code:
private readonly ObservableAsPropertyHelper<bool> _isLoading;
public bool IsLoading
{
get { return _isLoading.Value; }
}
LoadCommand = ReactiveCommand.CreateAsyncTask(async _ =>
{
//go do command stuff like fetch data from a database
}
LoadCommand.IsExecuting.ToProperty(this, x => x.IsLoading, out _isLoading);
//works if I have this line
var startSubscription = IsLoading;
LoadCommand.ExecuteAsyncTask();
and figured I should be able to do something like:
You've got the right idea, but the syntax is a bit off, try:
this.LoadCommand.IsExecuting
.ToProperty(this, x => x.IsLoading, out _isLoading);
If you were to do this with objects that can change (i.e. you've got a long expression), there's a special method called WhenAnyObservable that you use instead of WhenAnyValue:
this.WhenAnyObservable(x => x.SomeObjectThatMightBeReplaced.IsExecuting)
.ToProperty(this, x => x.IsLoading, out _isLoading);
I have run into this before and I think what you are experiencing lies here.
ToProperty / OAPH changes
ObservableAsPropertyHelper no longer is itself an IObservable, use WhenAny to observe it.
ObservableAsPropertyHelper now lazily Subscribes to the source only when the Value is read for the first time. This significantly improves performance and memory usage, but at the cost of some "Why doesn't my test work??" confusion. If you find that your ToProperty "isn't working", this may be why.
It is lazy, so you must subscribe to it (i.e. request a value from the property if using OAPH) for it to work. That is why you notice that your var startSubscription = IsLoading; 'fixes' the issue.
Knowing that made it easier for me to determine whether or not this was even an issue, or just something to keep in mind during my unit tests, knowing that in my application these properties would be bound to and hence subscribed to, making it moot in practice. You know, the whole "tree falling in the forest with no one there to hear it" idea.
I think you should stick with the ToProperty that you have, that seems the way to go IMHO.

How to capture Exception in nSpec

In my 'act' I want to capture an exception so that I can do multiple tests on the exception data. Examples on the web show how to capture and compare the type/message within a test (or 'It' block) but not how to capture the exception as an 'act' in itself.
I am currently just doing a try/catch within the 'act' body and storing the exception within the context for later testing in the 'It' block. There I can perform a number of different fluent assertions on the data. Is this the best approach?
Actually, there is indeed a better way to do this:
void describe_some_exceptional_behavior()
{
context["when throwing an exception"] = () =>
{
act = () => throw new InvalidOperationException();
it["should raise the exception"] = expect<InvalidOperationException>();
};
}
Note: you assign the result of expect directly to it. This tripped me up the first time.
See the nspec specs for more examples.
I don't think there currently is another way to achieve that apart from manual try catch blocks for storing the exception and later checking on it in an it block.
If you're willing to use an open-source framework, you could use Fluent Assertions and do this:
Action act = () => subject.Foo2("Hello");
act.ShouldThrow()
.WithInnerException()
.WithInnerMessage("whatever");

Resources