What is the difference between WhenPropertyChanged and ObservableForProperty - c#

public class Obj: ReactiveObject {
public Obj() {
this.WhenPropertyChanged(n => n.Prop)
.Subscribe(o =>
{
Foo();
});
this.ObservableForProperty(n => n.Prop)
.Subscribe(o =>
{
Foo2();
});
}
private bool _prop;
public bool Prop { get => _prop; set => this.RaiseAndSetIfChanged(ref _prop, value); }
public void Foo() {}
public void Foo2() {}
}
Both of these methods return IObservable<Obj, bool>. Description of both methods says that they observer property changes, yet only second reacts for changes (Foo2 is called).
What is difference between these methods and when they should be used? Documentation on https://www.reactiveui.net/ seesm to be outdated.

Related

c# unit testing method that calls EF Core extension method

I've been trying to unit test this simple method:
public void DeleteAllSettingsLinkedToSoftware(Guid softwareId)
{
_dbContext.Settings.Where(s => s.SoftwareId == softwareId).ForEachAsync(s => s.IsDeleted = true);
_dbContext.SaveChanges();
}
However I'm having a hard time unit testing this method from the moment the ForEachAsync() method gets called.
So far I've used Moq to setup the dbContext to return the proper settings when the Where() is executed.
My attempt:
Setup(m => m.ForEachAsync(It.IsAny<Action<Setting>>(), CancellationToken.None));
My question is: How will I unit test the call to the ForEachAsync() method?
I've read online that some people say it's impossible to unit test some static methods, if that's true in my case I'm curious about alternatives to test as much of this method as possible.
Edit
My complete test code:
[TestMethod]
public async Task DeleteAllSettingsLinkedToSoftware_Success()
{
//Arrange
var settings = new List<Setting>
{
new Setting
{
SoftwareId = SoftwareId1
},
new Setting
{
SoftwareId = SoftwareId1
},
new Setting
{
SoftwareId = SoftwareId1
},
new Setting
{
SoftwareId = SoftwareId2
}
}.AsQueryable();
var queryableMockDbSet = GetQueryableMockDbSet(settings.ToList());
queryableMockDbSet.As<IQueryable<Setting>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<Setting>(settings.Provider));
DbContext.Setup(m => m.Settings).Returns(queryableMockDbSet.Object);
_settingData = new SettingData(DbContext.Object, SettingDataLoggerMock.Object);
//Act
var result = await _settingData.DeleteAllSettingsLinkedToSoftwareAsync(SoftwareId1);
//Assert
DbContext.Verify(m => m.Settings);
DbContext.Verify(m => m.SaveChanges());
Assert.AreEqual(4, DbContext.Object.Settings.Count());
Assert.AreEqual(SoftwareId2, DbContext.Object.Settings.First().SoftwareId);
}
I am aware that my Assert still needs more checks.
The GetQueryableMockDbSet method:
public static Mock<DbSet<T>> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(s => sourceList.Add(s));
dbSet.Setup(d => d.AddRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(sourceList.AddRange);
dbSet.Setup(d => d.Remove(It.IsAny<T>())).Callback<T>(s => sourceList.Remove(s));
dbSet.Setup(d => d.RemoveRange(It.IsAny<IEnumerable<T>>())).Callback<IEnumerable<T>>(s =>
{
foreach (var t in s.ToList())
{
sourceList.Remove(t);
}
});
return dbSet;
}
You don't have to mock ForEachAsync at all. ForEachAsync returns Task and is being execute asynchronously this is the source of your problem.
Use async and await keywards to solve your problem:
public async void DeleteAllSettingsLinkedToSoftware(Guid softwareId)
{
await _dbContext.Settings.Where(s => s.SoftwareId == softwareId)
.ForEachAsync(s => s.IsDeleted = true);
_dbContext.SaveChanges();
}
Edit:
The new exception occurs because the supplied Provider is not a IDbAsyncQueryProvider.
Microsoft implemented a generic version of this interface: TestDbAsyncQueryProvider<TEntity>. Here is the implementation from the link:
internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider
{
private readonly IQueryProvider _inner;
internal TestDbAsyncQueryProvider(IQueryProvider inner)
{
_inner = inner;
}
public IQueryable CreateQuery(Expression expression)
{
return new TestDbAsyncEnumerable<TEntity>(expression);
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
{
return new TestDbAsyncEnumerable<TElement>(expression);
}
public object Execute(Expression expression)
{
return _inner.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return _inner.Execute<TResult>(expression);
}
public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(expression));
}
public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
{
return Task.FromResult(Execute<TResult>(expression));
}
}
internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }
public TestDbAsyncEnumerable(Expression expression)
: base(expression)
{ }
public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}
IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
IQueryProvider IQueryable.Provider
{
get { return new TestDbAsyncQueryProvider<T>(this); }
}
}
internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T>
{
private readonly IEnumerator<T> _inner;
public TestDbAsyncEnumerator(IEnumerator<T> inner)
{
_inner = inner;
}
public void Dispose()
{
_inner.Dispose();
}
public Task<bool> MoveNextAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_inner.MoveNext());
}
public T Current
{
get { return _inner.Current; }
}
object IDbAsyncEnumerator.Current
{
get { return Current; }
}
}
Now in the Setup you'll have to use it like:
mockSet.As<IQueryable<Setting>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<Setting>(data.Provider));
Disclaimer: I won't provide a direct solution, as requested by OP because I believe this question is a XY problem. Instead I will focus my answer on why is this code so damn hard to test, because yes, more than 30 lines of "arrange" to test 2 lines of code means that something went very wrong.
Short answer
This method doesn't need to be tested, at least at the unit level.
Long answer
The problem with the current implementation is a mix of concern.
The first line: _dbContext.Settings.Where(s => s.SoftwareId == softwareId).ForEachAsync(s => s.IsDeleted = true); contains business logic (s.softwareId == softwareId, s.IsDeleted = true) but also EF logic (_dbContext, ForEachAsync).
The second line: _dbContext.SaveChanges(); contains only EF logic
The point is: such methods (that mix concerns) are hard to test at the unit level. Hence the fact you need mocks and several dozens of "Arrange" code to test only 2 lines of implementation !
Based on this constatation you have 2 options:
You delete your test because the method is mainly containing EF logic which is useless to test (see this great series of articles for more details)
You extract business logic and write a real (and simple) unit test
In the second case, I would implement this logic so that I would be able to write a test like that:
[Test]
public void ItShouldMarkCorrespondingSettingsAsDeleted()
{
var setting1 = new Setting(guid1);
var setting2 = new Setting(guid2);
var settings = new Settings(new[] { setting1, setting2 });
settings.DeleteAllSettingsLinkedToSoftware(guid1);
Assert.That(setting1.IsDeleted, Is.True);
Assert.That(setting1.IsDeleted, Is.False);
}
Easy to write, easy to read.
How about the implementation now ?
public interface ISettings
{
void DeleteAllSettingsLinkedToSoftware(Guid softwareId);
}
public sealed class Settings : ISettings
{
private readonly IEnumerable<Setting> _settings;
public Settings(IEnumerable<Setting> settings) => _settings = settings;
public override void DeleteAllSettingsLinkedToSoftware(Guid softwareGuid)
{
foreach(var setting in _settings.Where(s => s.SoftwareId == softwareId))
{
setting.IsDeleted = true;
}
}
}
public sealed class EFSettings : ISettings
{
private readonly ISettings _source;
private readonly DBContext _dbContext;
public EFSettings(DBContext dbContext)
{
_dbContext = dbContext;
_source = new Settings(_dbContext.Settings);
}
public override void DeleteAllSettingsLinkedToSoftware(Guid softwareGuid)
{
_source.DeleteAllSettingsLinkedToSoftware(softwareGuid);
_dbContext.SaveChanges();
}
}
With a solution like this, each concern is separated which allows to:
Get rid of mocks
Really unit test business-logic code
Gain in maintainability and readability

Why can't the compiler figure out that this lambda is a Delegate?

Consider this tiny program.
public class Program
{
public static void Main()
{
// the first path compiles
RunAction(() => { });
// the second path does not compile
RunDelegate(() => {});
}
private static void RunAction(Action run) => RunDelegate(run);
private static void RunDelegate(Delegate run) { }
}
The first path compiles and implies that
the () => {} lambda is an Action,
the Action is a Delegate, and
therefor that the () => {} lambda is a Delegate.
Why does the second path not compile?
Usually the compiler is able to make the leap between steps (1) and (3). Here is an example of how the compiler usually handles this kind of nested is-a relationships.
public class Program2
{
public static void Main()
{
// both of these comple
AcceptPerson(new Programmer());
AcceptAnimal(new Programmer());
}
private static void AcceptPerson(Person p) => AcceptAnimal(p);
private static void AcceptAnimal(Animal a) { }
}
public class Programmer : Person { }
public class Person : Animal { }
public class Animal { }
There is no "default" delegate type for an anonymous function such as () => { }. Such an expression is implicitly convertible to any concrete delegate type of the right signature and return type (subject to various natural variance rules).
You can have many delegate types that match:
namespace TestFramework
{
public delegate void TestDelegate();
}
namespace System
{
public delegate void Action();
}
namespace System.Threading
{
public delegate void ThreadStart();
}
...
Among all such possible concrete delegate types (each of which as the abstract System.Delegate as its (indirect) base class) there is no preferred one.
There is an implicit conversion from the expression () => { } to each of them:
TestDelegate f = () => { };
Action g = () => { };
ThreadStart h = () => { };
...
Because of the implicit conversion, your call RunAction(() => { }); works.
But with RunDelegate(() => {}); there is no telling what concrete delegate type to use. You have to do one of:
RunDelegate((TestDelegate)(() => { }));
RunDelegate((Action)(() => { }));
RunDelegate((ThreadStart)(() => { }));
...
The comments to your question are correct.
Related to this is the fact that this will not compile:
var f = () => { }; // illegal, shows that '() => { }' does NOT have type System.Action
And you cannot use a sub-expression like myBool ? (() => { }) : null, and so on.

Appropriate way to mock Func<>

Hi I am trying to mock the following thing:
var result = _scope.Execute<FooService, IList<FooEntity>>(x => x.GetFooEntities(fooModel));
This is how I try to mock it:
_mockedScope
.Setup(x => x.Execute<FooService, IList<FooEntity>>(f => f.GetFooEntities(It.IsAny<FooModel>())))
.Returns(new List<FooEntity>)
But when I run the test it throws me an exception
Unsupported expression: s => s.GetFooEntities(IsAny())
Any suggestions how can I mock it?
Here is an example what i want to moq
public class Test
{
private readonly IScope _scope;
public Test(IScope scope)
{
_scope = scope;
}
public void Foo()
{
var foo = new FooEntity();
Result<IList<Foo>> result =
_scope.Execute<FooService, IList<Foo>>(
"f",
s => s.GetFoo(foo));
}
}
public class Foo
{
}
public class FooEntity
{
}
public class FooService
{
public List<Foo> GetFoo(FooEntity f);
}
public interface IScope
{
Result<TResult> Execute<T1, TResult>(string temp, Func<T1, TResult> function);
}
public class Result<T>
{
private Result(T value, Exception exception)
{
Value = value;
Error = exception;
}
public Exception Error { get; }
public T Value { get; }
public bool HasError => Error != null;
public static Result<T> Fail(Exception exception) => new Result<T>(default(T), exception);
public static Result<T> Success(T value) => new Result<T>(value, null);
}
While expressions are used by moq to setup mocks, you are trying to mock an expression. This tends to be very difficult with Moq but there are workarounds via matched arguments.
Assuming Scope.Execute method is defined like
public interface IScope {
Result<TResult> Execute<T, TResult>(string temp, Func<T, TResult> function);
}
Use It.IsAny to allow for flexibility when setting up a mock that relies on an expression argument.
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
The It.IsAny<Func<FooService, IList<Foo>>>() will cover s => s.GetFoo(foo) in the invoked code.
Given
public class Test {
private readonly IScope _scope;
public Test(IScope scope) {
_scope = scope;
}
public IList<Foo> Foo() {
var foo = new FooEntity();
Result<IList<Foo>> result = _scope.Execute<FooService, IList<Foo>>("f", s => s.GetFoo(foo));
var value = result.Value;
return value;
}
}
The following complete example was used to demonstrate what was explained above
[TestClass]
public class ExpressionMock {
[TestMethod]
public void TestFoo() {
//Arrange
var _mockedScope = new Mock<IScope>();
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
var subject = new Test(_mockedScope.Object);
//Act
var actual = subject.Foo();
//Assert
actual.Should().NotBeNull();
}
}
Reference Moq Quickstart to get a better understanding of how to use the framework

subscribe as last method raised

Is there a way to subscribe a method though it would be called last when the onNext is raised?
m_subject.Subscribe(() => Console.writeLine("firstSubscription");
m_subject.SubscribeLast(() => Console.writeLine("secondSubscription");
m_subject.Subscribe(() => Console.writeLine("thirdSubscription");
m_subject.OnNext();
// prints:
// firstSubscription
// thirdSubscription
// secondSubscription
You cannot have a subscriber be executed last, but you can wrap all your calls in a single subscription.
Something like that:
Action action = () => {};
Action lastAction = () => {};
m_subject.Subscribe(() =>
{
action();
lastAction();
});
action += (() => Console.writeLine("firstSubscription");
lastAction += (() => Console.writeLine("secondSubscription");
action += (() => Console.writeLine("thirdSubscription");
m_subject.OnNext();
// prints:
// firstSubscription
// thirdSubscription
// secondSubscription
You can also do this by defining a custom Subject<T> which internally has a default subject and also a last subject.
Update
I added overloads of ObserveOn to store the IScheduler and SynchronizationContext and then apply those at the time of subscription. Similar technique can be used to enable SubscribeOn to work as well.
public class SubscribeLastSubject<T> : ISubject<T>, IDisposable
{
private readonly Subject<T> subject = new Subject<T>();
private readonly Subject<T> lastSubject = new Subject<T>();
private IScheduler observeScheduler;
private SynchronizationContext observerContext;
public void OnNext(T value)
{
subject.OnNext(value);
lastSubject.OnNext(value);
}
public void OnError(Exception error)
{
subject.OnError(error);
lastSubject.OnError(error);
}
public void OnCompleted()
{
subject.OnCompleted();
lastSubject.OnCompleted();
}
public IDisposable Subscribe(IObserver<T> observer)
{
return GetObservable().Subscribe(observer);
}
public IDisposable SubscribeLast(IObserver<T> observer)
{
return GetLastObservable().Subscribe(observer);
}
public IDisposable SubscribeLast(Action<T> action)
{
return GetLastObservable().Subscribe(action);
}
public SubscribeLastSubject<T> ObserveOn(IScheduler scheduler)
{
observeScheduler = scheduler;
return this;
}
public SubscribeLastSubject<T> ObserveOn(SynchronizationContext context)
{
observerContext = context;
return this;
}
public void Dispose()
{
subject.Dispose();
lastSubject.Dispose();
}
private IObservable<T> GetObservable()
{
if (observerContext != null)
{
return subject.ObserveOn(observerContext);
}
if (observeScheduler != null)
{
return subject.ObserveOn(observeScheduler);
}
return subject;
}
private IObservable<T> GetLastObservable()
{
if (observerContext != null)
{
return lastSubject.ObserveOn(observerContext);
}
if (observeScheduler != null)
{
return lastSubject.ObserveOn(observeScheduler);
}
return lastSubject;
}
}
Usage
var m_subject = new SubscribeLastSubject<string>();
m_subject.ObserveOn(Scheduler.CurrentThread).Subscribe(s => Console.WriteLine("firstSubscription"));
m_subject.ObserveOn(Scheduler.CurrentThread).SubscribeLast(s => Console.WriteLine("secondSubscription"));
m_subject.ObserveOn(Scheduler.CurrentThread).Subscribe(s => Console.WriteLine("thirdSubscription"));
m_subject.OnNext("1");
Console.ReadKey();
Output
firstSubscription
thirdSubscription
secondSubscription

StructureMap default instance and additional with explicit arguments

I've got an interface and a class that implements that interface. That class has a default static instance and can also be constructed explicitly (passing an argument).
How do i configure StrucutreMap so that default instance is the static instance, and if i request an instance with an argument a new one is constructed?
Here's the test that fails
[TestFixture]
public class StructureMapTests
{
[Test]
public void Test_same_interface_default_implemenation_and_with_parameter()
{
IMyInterface defaultImp = new MyImpl(0);
ObjectFactory.Initialize(x =>
{
x.For<IMyInterface>().Use(defaultImp);
x.For<IMyInterface>().Add<MyImpl>().Ctor<int>().IsTheDefault();
});
Assert.AreEqual(defaultImp, ObjectFactory.GetInstance<IMyInterface>());
var instance1 = ObjectFactory.With("value").EqualTo(1).GetInstance<IMyInterface>();
Assert.AreEqual(true, instance1 != defaultImp); //<-- fails here
Assert.AreEqual(1, instance1.GetValue());
var instance2 = ObjectFactory.With("value").EqualTo(2).GetInstance<IMyInterface>();
Assert.AreEqual(true, instance1 != defaultImp);
Assert.AreEqual(2, instance2.GetValue());
}
public interface IMyInterface
{
int GetValue();
}
public class MyImpl : IMyInterface
{
private int _value;
public MyImpl(int value)
{
_value = value;
}
public int GetValue()
{
return _value;
}
}
}
I think that the problem that you are facing is that when registering multiple implementations for the same interface, the last one is the one that is going to be resolved by GetInstance. To solve this, you could name your configurations.
Try the following:
[TestFixture]
public class StructureMapTests
{
[Test]
public void Test_same_interface_default_implemenation_and_with_parameter()
{
IMyInterface defaultImp = new MyImpl(0);
ObjectFactory.Initialize(x =>
{
x.For<IMyInterface>().Add<MyInterface>().Named("withArgument").Ctor<int>().IsTheDefault();
x.For<IMyInterface>().Use(defaultImp).Named("default");
});
Assert.AreEqual(defaultImp, ObjectFactory.GetInstance<IMyInterface>());
var instance1 = ObjectFactory.With("value").EqualTo(1).GetInstance<IMyInterface>("withArgument");
Assert.AreEqual(true, instance1 is MyInterface);
Assert.AreEqual(1, instance1.GetValue());
var instance2 = ObjectFactory.With("value").EqualTo(2).GetInstance<IMyInterface>("withArgument");
Assert.AreEqual(true, instance2 is MyInterface);
Assert.AreEqual(2, instance2.GetValue());
}
public interface IMyInterface
{
int GetValue();
}
private class MyInterface : IMyInterface
{
private int _value;
public MyInterface(int value)
{
_value = value;
}
public int GetValue()
{
return _value;
}
}
}

Categories