Recommended way to test Scheduler/Throttle - reactiveui

I'm in the process of rewriting one little WPF-App I wrote to make use of ReactiveUI, to get a feeling about the library.
I really like it so far!
Now I've stumbled upon the Throttle method and want to use it when applying a filter to a collection.
This is my ViewModel:
namespace ReactiveUIThrottle
{
public class MainViewModel : ReactiveObject
{
private string _filter;
public string Filter { get => _filter; set => this.RaiseAndSetIfChanged(ref _filter, value); }
private readonly ReactiveList<Person> _persons = new ReactiveList<Person>();
private readonly ObservableAsPropertyHelper<IReactiveDerivedList<Person>> _filteredPersons;
public IReactiveDerivedList<Person> Persons => _filteredPersons.Value;
public MainViewModel()
{
Filter = string.Empty;
_persons.AddRange(new[]
{
new Person("Peter"),
new Person("Jane"),
new Person("Jon"),
new Person("Marc"),
new Person("Heinz")
});
var filterPersonsCommand = ReactiveCommand.CreateFromTask<string, IReactiveDerivedList<Person>>(FilterPersons);
this.WhenAnyValue(x => x.Filter)
// to see the problem
.Throttle(TimeSpan.FromMilliseconds(2000), RxApp.MainThreadScheduler)
.InvokeCommand(filterPersonsCommand);
_filteredPersons = filterPersonsCommand.ToProperty(this, vm => vm.Persons, _persons.CreateDerivedCollection(p => p));
}
private async Task<IReactiveDerivedList<Person>> FilterPersons(string filter)
{
await Task.Delay(500); // Lets say this takes some time
return _persons.CreateDerivedCollection(p => p, p => p.Name.Contains(filter));
}
}
}
The filtering itself works like a charm, also the throttling, when using the GUI.
However, I'd like to unittest the behavior of the filtering and this is my first attempt:
[Test]
public void FilterPersonsByName()
{
var sut = new MainViewModel();
sut.Persons.Should().HaveCount(5);
sut.Filter = "J";
sut.Persons.Should().HaveCount(2);
}
This test fails because the collection still has 5 people.
When I get rid of the await Task.Delay(500) in FilterPersons then the test will pass, but takes 2 seconds (from the throttle).
1) Is there a way to have the throttle be instant within the test to speed up the unittest?
2) How would I test the async behavior in my filter?
I'm using ReactiveUI 7.x

Short answers:
Yes, by making sure you're using CurrentThreadScheduler.Instance when running under test
Instead of using CurrentThreadScheduler, use a TestScheduler and manually advance it
The longer answer is that you need to ensure your unit tests can control the scheduler being used by your System Under Test (SUT). By default, you'll generally want to use CurrentThreadScheduler.Instance to make things happen "instantly" without any need to advance the scheduler manually. But when you want to write tests that do validate timing, you use a TestScheduler instead.
If, as you seem to be, you're using RxApp.*Scheduler, take a look at the With extension method, which can be used like this:
(new TestScheduler()).With(sched => {
// write test logic here, and RxApp.*Scheduler will resolve to the chosen TestScheduler
});
I tend to avoid using the RxApp ambient context altogether for the same reason I avoid all ambient contexts: they're shared state and can cause trouble as a consequence. Instead, I inject an IScheduler (or two) into my SUT as a dependency.

Related

Is CoroutineScope(SupervisorJob()) runs in Main scope?

I was doing this code lab
https://developer.android.com/codelabs/android-room-with-a-view-kotlin#13
and having a question
class WordsApplication : Application() {
// No need to cancel this scope as it'll be torn down with the process
val applicationScope = CoroutineScope(SupervisorJob())
// Using by lazy so the database and the repository are only created when they're needed
// rather than when the application starts
val database by lazy { WordRoomDatabase.getDatabase(this, applicationScope) }
val repository by lazy { WordRepository(database.wordDao()) }
}
private class WordDatabaseCallback(
private val scope: CoroutineScope
) : RoomDatabase.Callback() {
override fun onCreate(db: SupportSQLiteDatabase) {
super.onCreate(db)
INSTANCE?.let { database ->
scope.launch {
var wordDao = database.wordDao()
// Delete all content here.
wordDao.deleteAll()
// Add sample words.
var word = Word("Hello")
wordDao.insert(word)
word = Word("World!")
wordDao.insert(word)
// TODO: Add your own words!
word = Word("TODO!")
wordDao.insert(word)
}
}
}
}
this is the code I found, as you can see, it is directly calling scope.launch(...)
my question is that:
isn't all the Room operations supposed to run in non-UI scope? Could someone help me to understand this? thanks so much!
Is CoroutineScope(SupervisorJob()) runs in Main scope?
No. By default CoroutineScope() uses Dispatchers.Default, as can be found in the documentation:
CoroutineScope() uses Dispatchers.Default for its coroutines.
isn't all the Room operations supposed to run in non-UI scope?
I'm not very familiar specifically with Room, but generally speaking it depends if the operation is suspending or blocking. You can run suspend functions from any dispatcher/thread. deleteAll() and insert() functions in the example are marked as suspend, therefore you can run them from both UI and non-UI threads.

How to perform new operation on #RetryOnFailure by jcabi

Iam using jcabi-aspects to retry connection to my URL http://xxxxxx:8080/hello till the connection comes back.As you know #RetryOnFailure by jcabi has two fields attempts and delay.
I want to perform the operation like attempts(12)=expiryTime(1 min=60000 millis)/delay(5 sec=5000 millis) on jcabi #RetryOnFailure.How do i do this.The code snippet is as below.
#RetryOnFailure(attempts = 12, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
You can combine two annotations:
#Timeable(unit = TimeUnit.MINUTE, limit = 1)
#RetryOnFailure(attempts = Integer.MAX_VALUE, delay = 5)
public String load(URL url) {
return url.openConnection().getContent();
}
#RetryOnFailure will retry forever, but #Timeable will stop it in a minute.
The library you picked (jcabi) does not have this feature. But luckily the very handy RetryPolicies from Spring-Batch have been extracted (so you can use them alone, without the batching):
Spring-Retry
One of the many classes you could use from there is TimeoutRetryPolicy:
RetryTemplate template = new RetryTemplate();
TimeoutRetryPolicy policy = new TimeoutRetryPolicy();
policy.setTimeout(30000L);
template.setRetryPolicy(policy);
Foo result = template.execute(new RetryCallback<Foo>() {
public Foo doWithRetry(RetryContext context) {
// Do stuff that might fail, e.g. webservice operation
return result;
}
});
The whole spring-retry project is very easy to use and full of features, like backOffPolicies, listeners, etc.

How to get Unit component? Can i use addAsync for get solution?

I want to built a program which is get problems and I found that my first batches of tests involving custom components would tend to follow code:
import mx.core.Application;   
 import mx.events.FlexEvent;
 import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
private var component:CustomComponent;
public function testSomeAspect() : void {
component = new CustomComponent();
component.addEventListener(FlexEvent.CREATION_COMPLETE,
addAsync(verifySomeAspect, 5000));
component.height = 0;
component.width = 0;
Application.application.addChild(component);
}
public function verifySomeAspect(event:FlexEvent) : void {}
override public function tearDown() : void {
 try {
if (component) {
Application.application.removeChild(component);
component = null;
}
} catch (e:Error) {
 }
}
First, you need to make sure the component has been fully initialized before you can reliably verify anything about it, and in Flex this happens asynchronously after it has been added to the display list. So you need to setup a callback (using FlexUnit's addAsync function) to be notified when that's happened.
Lately i've been just manually calling the methods that the runtime would call for you in the necessary places, so now my tests tend to look more like this:
import flexunit.framework.TestCase;
public class CustomComponentTest extends TestCase {
public function testSomeAspect() : void {
var component:CustomComponent = new CustomComponent();
 component.initialize();
component.validateProperties();
}
This is much easier to follow, but it kinda feels like I'm cheating a little either way. The first case is slamming it into the current Application (which would be the unit test runner shell app), and the latter isn't a "real" environment.I was wondering how other people would handle this sort of situation?
I can agree that the second version is shorter, but I'm not sure that I think it's easier to follow. The test does a lot of things that you wouldn't normally do, whereas the first example is more true to how you would use the component outside the test environment.
Also, in the second form you have to make sure that you do exactly what the framework would do, miss one step and your test isn't relevant, and each test must repeat this code. Seems to me it's better to test it in a situation that is as close to the real thing as possible.
You could have a look at dpUint's sequences, they made component testing a little more declarative:
public function testLogin():void {
var passThroughData:Object = new Object();
passThroughData.username = "myuser1";
passThroughData.password = "somepsswd";
var sequence:SequenceRunner = new SequenceRunner(this);
sequence.addStep(new SequenceSetter(form.usernameTI,
{text:passThroughData.username}));
sequence.addStep(new SequenceWaiter(form.usernameTI,
FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceSetter(form.passwordTI,
{text:passThroughData.password}));
sequence.addStep(new SequenceWaiter(form.passwordTI, FlexEvent.VALUE_COMMIT, 100));
sequence.addStep(new SequenceEventDispatcher(form.loginBtn,
new MouseEvent("click", true, false)));
sequence.addStep(new SequenceWaiter(form, "loginRequested", 100));
sequence.addAssertHandler(handleLoginEvent, passThroughData);
sequence.run();}

NHibernate Overcoming NotSupportedException

Does anyone know of any way to overcome NotSupportedException? I have a method against a User:
public virtual bool IsAbove(User otherUser)
{
return HeirarchyString.StartsWith(otherUser.HeirarchyString);
}
And I want to do:
_session.Query<User>.Where(x => loggedInUser.IsAbove(x));
But this throws a NotSupportedException. The real pain though is that using
_session.Query<User>.Where(x => loggedInUser.HeirarchyString.StartsWith(x.HeirarchyString));
works absolutely fine. I don't like this as a solution, however, because it means that if I change how the IsAbove method works, I have to remember all the places where I have duplicated the code whenever I want to update it
Name the specification expression and reuse that, e.g:
public Expression<Func<....>> IsAboveSpecification = (...) => ...;
public virtual bool IsAbove(User otherUser)
{
return IsAboveSpecification(HeirarchyString, otherUser.HeirarchyString);
}
Reuse IsAboveSpecification in the query as needed. If the IsAbove() method is used often use can cache the result of the Compile() method on the expression.

How to mock up a static method in a static class with URLHelp? (Moq)

I have a extension method. Can any one help me how to test this method with Moq?
public static string GetBaseUrl(this UrlHelper urlHelper)
{
Uri contextUri = new Uri(urlHelper.RequestContext.HttpContext.Request.Url, urlHelper.RequestContext.HttpContext.Request.RawUrl);
UriBuilder realmUri = new UriBuilder(contextUri) { Path = urlHelper.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
string url = realmUri.Uri.AbsoluteUri;
if (url.EndsWith("/"))
{
url = url.Remove(url.Length - 1, 1);
}
return url;
}
many thanks.
As TrueWill points out, you can't use Moq directly with UrlHelper.RequestContext because it isn't virtual. On the other hand, UrlHelper is a public class that you can instantiate for use with unit testing.
At some point, however, you will encounter the need to assign a HttpContextBase to create the UrlHelper, and Moq can help you to do that.
Here's a test that shows that I can at least write a unit test that invokes your GetBaseUrl without throwing any exceptions:
[TestMethod]
public void Test1()
{
var httpCtxStub = new Mock<HttpContextBase>();
httpCtxStub.SetupGet(x => x.Request).Returns(() =>
{
var reqStub = new Mock<HttpRequestBase>();
reqStub.SetupGet(r => r.RawUrl).Returns("http://foo");
reqStub.SetupGet(r => r.Url).Returns(new Uri("http://foo"));
return reqStub.Object;
});
var requestCtx = new RequestContext(httpCtxStub.Object, new RouteData());
var urlHelper = new UrlHelper(requestCtx, new RouteCollection());
var result = urlHelper.GetBaseUrl();
// Assert something
}
However, this isn't the simplest unit test to write and maintain, so I support TrueWill's comment that you might make life simpler for yourself if you hide UrlHelper behind an interface.
The UrlHelper.RequestContext property is non-virtual. Moq isn't going to be of help in this case, to the best of my knowledge.
You could create a wrapper class for UrlHelper that implements an interface, but that would seem to defeat the purpose of using an extension method.
Typemock would probably do what you want, if you have the budget for a commercial program. (I haven't tried it; I use Moq myself.)
Another option would be to write integration tests against this method; while they would run more slowly than unit tests, I suspect this method is unlikely to version often.
A larger issue is coupling to UrlHelper reducing testability in the rest of your application. Perhaps other posters can suggest answers to that issue.

Resources