How to fake delegates with FakeItEasy - fakeiteasy

When i try to fake a delegate-type, i get System.InvalidCastException
[TestMethod]
public void TestDelegateFake()
{
var func = A.Fake<Func<long, object>>();
A.CallTo(() => func(A<long>.Ignored))
.Returns(new {});
func(123);
}
How du i fake delegates?

I think you have to specify the Invoke-method explicitly:
A.CallTo(() => func.Invoke(A<long>.Ignored)).Returns(new {});

Related

ArgumentNullException when invoking RenderComponent with Action

I am trying to test a custom Razor component with an EventBack parameter:
#code {
[Parameter]
public EventCallback OnClick { get; set; }
}
I am using bUnit with xUnit to try to test EventCallback. Here's my test method:
public void TestOnClickEvent()
{
void TestOnClick()
{
Assert.True(true);
}
IRenderedComponent<CSInput> component =
RenderComponent<CSInput>(
builder => builder.Add(
instanceOfCSInput => instanceOfCSInput.OnClick,
TestOnClick));
component.Find("input").Click();
}
When I tried to run the test, I get an ArgumentNullException from RenderComponent(), but I have no idea what could it be since everything is all in lambda.
Apparently, the location function is the issue. I replace the call to the local function with another lambda and it works!
IRenderedComponent<CSInput> component =
RenderComponent<CSInput>(
builder => builder.Add(
instanceOfCSInput => instanceOfCSInput.OnClick,
() => Assert.True(true)));

Dialog interaction requests using IObservable

I'm using reactive programming to build an MVVM app and am trying to figure out how my view model can raise a question and wait for a dialog to prompt the user for an answer.
For example, when the user clicks a Rename button I want a dialog to pop up that allows the user to change the text. My approach is for the view model to expose an IObservable<string> property. Code-behind in the View listens for emitted values and might display a UWP ContentDialog. If the user changes the text and clicks OK, code in that dialog would call ReportResult(string newText) on view model. I've got some code below to show how it works. Two questions:
Is this a reasonable approach for collecting information from the user?
Also, I've got two subtly different approaches for building this and don't know which is better.
interface IServiceRequest<TSource, TResult> : ISubject<TResult, TSource> { }
// Requests for information are just 'passed through' to listeners, if any.
class ServiceRequestA<TSource, TResult> : IServiceRequest<TSource, TResult>
{
IObservable<TSource> _requests;
Subject<TResult> _results = new Subject<TResult>();
public ServiceRequestA(IObservable<TSource> requests)
{
_requests = requests;
}
public IObservable<TResult> Results => _results;
public void OnCompleted() => _results.OnCompleted();
public void OnError(Exception error) => _results.OnError(error);
public void OnNext(TResult value) => _results.OnNext(value);
public IDisposable Subscribe(IObserver<TSource> observer) => _requests.Subscribe(observer);
}
// Requests for information are 'parked' inside the class even if there are no listeners
// This happens when InitiateRequest is called. Alternately, this class could implement
// IObserver<TSource>.
class ServiceRequestB<TSource, TResult> : IServiceRequest<TSource, TResult>
{
Subject<TSource> _requests = new Subject<TSource>();
Subject<TResult> _results = new Subject<TResult>();
public void InitiateRequest(TSource request) => _requests.OnNext(request);
public IObservable<TResult> Results => _results;
public void OnCompleted() => _results.OnCompleted();
public void OnError(Exception error) => _results.OnError(error);
public void OnNext(TResult value) => _results.OnNext(value);
public IDisposable Subscribe(IObserver<TSource> observer) => _requests.Subscribe(observer);
}
class MyViewModel
{
ServiceRequestA<string, int> _serviceA;
ServiceRequestB<string, int> _serviceB;
public MyViewModel()
{
IObservable<string> _words = new string[] { "apple", "banana" }.ToObservable();
_serviceA = new ServiceRequestA<string, int>(_words);
_serviceA
.Results
.Subscribe(i => Console.WriteLine($"The word is {i} characters long."));
WordSizeServiceRequest = _serviceA;
// Alternate approach using the other service implementation
_serviceB = new ServiceRequestB<string, int>();
IDisposable sub = _words.Subscribe(i => _serviceB.InitiateRequest(i)); // should dispose later
_serviceB
.Results
.Subscribe(i => Console.WriteLine($"The word is {i} characters long."));
WordSizeServiceRequest = _serviceB;
}
public IServiceRequest<string, int> WordSizeServiceRequest { get; set; }
// Code outside the view model, probably in the View code-behind, would do this:
// WordSizeServiceRequest.Select(w => w.Length).Subscribe(WordSizeServiceRequest);
}
Based on comments from Lee Campbell, here is a different approach. Maybe he'll like it better? I'm actually not sure how to build the IRenameDialog. Before it was just a bit of code-behind in the View.
public interface IRenameDialog
{
void StartRenameProcess(string original);
IObservable<string> CommitResult { get; }
}
public class SomeViewModel
{
ObservableCommand _rename = new ObservableCommand();
BehaviorSubject<string> _name = new BehaviorSubject<string>("");
public SomeViewModel(IRenameDialog renameDialog,string originalName)
{
_name.OnNext(originalName);
_rename = new ObservableCommand();
var whenClickRenameDisplayDialog =
_rename
.WithLatestFrom(_name, (_, n) => n)
.Subscribe(n => renameDialog.StartRenameProcess(n));
var whenRenameCompletesPrintIt =
renameDialog
.CommitResult
.Subscribe(n =>
{
_name.OnNext(n);
Console.WriteLine($"The new name is {n}");
};
var behaviors = new CompositeDisposable(whenClickRenameDisplayDialog, whenRenameCompletesPrintIt);
}
public ICommand RenameCommand => _rename;
}
Hmm.
The first block of code looks like a re-implementation of IObservable<T>, actually I think event worse ISubject<T>, so that raises alarm bells.
Then the MyViewModel class does other things like pass IObservable<string> as a parameter (Why?), create subscriptions (side effects) in the constructor, and expose a Service as a public property. You also metion having code in your view code behind, which is often a code-smell in MVVM too.
I would suggest reading up on MVVM (solved problem for 10yrs) and havnig a look at how other Client applications use Rx/Reactive programming with MVVM (solved problem for ~6yrs)
Lee shamed me into coming up with a better solution. The first and best turned out to be very simple. I pass into the constructor one of these:
public interface IConfirmationDialog
{
Task<bool> Show(string message);
}
Inside my view model, I can do something like this...
IConfirmationDialog dialog = null; // provided by constructor
_deleteCommand.Subscribe(async _ =>
{
var result = await dialog.Show("Want to delete?");
if (result==true)
{
// delete the file
}
});
Building a ConfirmationDialog wasn't hard. I just create one of these in the part of my code that creates view models and assigns them to views.
public class ConfirmationDialogHandler : IConfirmationDialog
{
public async Task<bool> Show(string message)
{
var dialog = new ConfirmationDialog(); // Is subclass of ContentDialog
dialog.Message = message;
var result = await dialog.ShowAsync();
return (result == ContentDialogResult.Primary);
}
}
So the solution above is pretty clean; dependencies my view model needs are provided in the constructor. Another approach similar to what Prism and ReactiveUI do is one where the ViewModel is constructed without the dependency it needs. Instead there is a bit of code-behind in the view to fill in that dependency. I don't need to have multiple handlers, so I just have this:
public interface IInteractionHandler<TInput, TOutput>
{
void SetHandler(Func<TInput, TOutput> handler);
void RemoveHandler();
}
public class InteractionBroker<TInput, TOutput> : IInteractionHandler<TInput, TOutput>
{
Func<TInput, TOutput> _handler;
public TOutput GetResponse(TInput input)
{
if (_handler == null) throw new InvalidOperationException("No handler has been defined.");
return _handler(input);
}
public void RemoveHandler() => _handler = null;
public void SetHandler(Func<TInput, TOutput> handler) => _handler = handler ?? throw new ArgumentNullException();
}
And then my ViewModel exposes a property like this:
public IInteractionHandler<string,Task<bool>> Delete { get; }
And handles the delete command like this:
_deleteCommand.Subscribe(async _ =>
{
bool shouldDelete = await _deleteInteractionBroker.GetResponse("some file name");
if (shouldDelete)
{
// delete the file
}
});

How to convert callbacks to Rx.Observable?

If an external library offers only to register a callback instead of an event, what is the best way to create an Observable from it?
If it where an event I could use Observable.FromEventPattern but in this case the only idea I have is to use a Subjectand queue events in it on each callback.
Is there any better way to do this?
Use Observable.Create. Here's an example:
void Main()
{
var target = new SampleCallbacker();
var actionB = new Action<int>(i => Console.WriteLine($"{i} * {i} = {i * i}."));
target.Register(actionB);
var observable = Observable.Create<int>(observer =>
{
var action = new Action<int>(i => observer.OnNext(i));
target.Register(action);
return () => target.Unregister(action);
});
var subscription = observable.Subscribe(i => Console.WriteLine($"From observable: {i} was fired."));
target.Fire(1);
target.Fire(2);
target.Fire(3);
Console.WriteLine("Unsusbscribing observable...");
subscription.Dispose();
target.Fire(4);
target.Fire(5);
}
class SampleCallbacker
{
private List<Action<int>> _actions = new List<System.Action<int>>();
public void Register(Action<int> action)
{
_actions.Add(action);
}
public void Unregister(Action<int> action)
{
while (_actions.Remove(action))
{} //loop remove
}
public void Fire(int i)
{
foreach (var action in _actions)
{
action(i);
}
}
}

WebAPI Moq Async EF6 UnitTesting

I'm using Moq to make Mocks for the EF6 Async methods. But something is not working right because i get the following exception:
The source IQueryable doesn't implement IDbAsyncEnumerable{0}. Only
sources that implement IDbAsyncEnumerable can be used for Entity
Framework asynchronous operations. For more details see
http://go.microsoft.com/fwlink/?LinkId=287068.
I have the following code:
UnitTest1.cs
var mockSet = new Mock<DbSet<MyModel>>();
mockSet.As<IDbAsyncEnumerable<MyModel>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<MyModel>(data.GetEnumerator()));
mockSet.As<IQueryable<MyModel>>()
.Setup(m => m.Provider)
.Returns(new TestDbAsyncQueryProvider<MyModel>(data.Provider));
mockSet.As<IQueryable<MyModel>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<MyModel>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<MyModel>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<PDBContext>();
mockContext.Setup(c => c.GetSet<MyModel>()).Returns(mockSet.Object);
//Test!
var controller = new MyModelController();
controller.MyModelStore = new MyModelStore(mockContext.Object);
var result = await controller.GetBestOppertunity(2) as OkNegotiatedContentResult<List<MyModel>>;
//Result
Assert.IsNotNull(result);
Assert.AreEqual(2, result.Content.Count);
MyModelStore.cs
public async Task<List<MyModel>> GetBestOppertunity(int limit)
{
return await Context.GetSet<MyModel>().OrderByDescending(x => x.StartDate).Take(limit).ToListAsync();
}
I based the code on the following blog to prevent the error from happening: http://msdn.microsoft.com/en-us/data/dn314429
But exactly the error happends that i'm tryging to prevent. The error is explained here: http://msdn.microsoft.com/en-US/data/dn313107
The Error happends in the code: GetBestOppertunity(int limit) in MyModelStore.cs.
The GetSet Method showed there is nothing more than a wrapper to be able to attach unit testing to the Set method.
PDBContext.cs (DatabaseFirst)
public partial class PDBContext : IPDBContext
{
public virtual IDbSet<T> GetSet<T>() where T : class
{
return Set<T>();
}
}
Any Ideas what i'm doing wrong?

How do you mock adding items to a repository or DbContext using moq?

The examples I've seen for using moq for a repository only show how to mock things being returned. I have a somewhat strange requirement: when a query is executed, if a condition exists, a certain item should be added to the repository. I am wondering how to test this without querying the database. I know how to mock the condition existing, but then how do you setup the mock so that you can test that the certain item is added?
Try to use fake in memory repository instead of moq, for example universal generic repository for all entities:
public interface IInMemoryRepository<T> where T : class
{
IQueryable<T> GetAll();
void Create(T item);
void Update(T item);
T GetItem(Expression<Func<T, bool>> expression);
void Delete(T item);
}
public class InMemoryRepository<T> : IInMemoryRepository<T> where T : class
{
private int _incrementer = 0;
public Dictionary<int, T> List = new Dictionary<int, T>();
public IQueryable<T> GetAll()
{
return List.Select(x => x.Value).AsQueryable();
}
public void Create(T item)
{
_incrementer++;
item.GetType().GetProperties().First(p => p.Name == "Id").SetValue(item, _incrementer, null);
List.Add(_incrementer, item);
}
public void Update(T item)
{
var key = (int)item.GetType().GetProperties().First(p => p.Name == "Id").GetValue(item, null);
List[key] = item;
}
public T GetItem(Expression<Func<T, bool>> expression)
{
return List.Select(x => x.Value).SingleOrDefault(expression.Compile());
}
public void Delete(T item)
{
var key = (int)item.GetType().GetProperties().First(p => p.Name == "Id").GetValue(item, null);
List.Remove(key);
}
}
You would not mock the repository; you would have an alternate repository that would use an in-memory store instead of the database, then use IoC to select the correct repository implementation for tests/code.
This blog article might be of use, although my design has changed somewhat since I wrote the post and I really need to update it. I used teh generic repository pattern in a way that enables the DbContext to be mocked. This allows the data access layer to be tested 'right up to the edges'.
Times have changed -- since the release of Entity Framework 6 it has become much easier to mock database context and datasets. This article outlines the particulars.
Testing non-query scenarios
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Data.Entity;
namespace TestingDemo
{
[TestClass]
public class NonQueryTests
{
[TestMethod]
public void CreateBlog_saves_a_blog_via_context()
{
var mockSet = new Mock<DbSet<Blog>>();
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
service.AddBlog("ADO.NET Blog", "http://blogs.msdn.com/adonet");
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
}
}
Testing query scenarios
Query testing is pretty sweet now, because you can build up test data sets in code and then execute your tests against them:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
namespace TestingDemo
{
[TestClass]
public class QueryTests
{
[TestMethod]
public void GetAllBlogs_orders_by_name()
{
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
}.AsQueryable();
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(0 => data.GetEnumerator());
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(c => c.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
var blogs = service.GetAllBlogs();
Assert.AreEqual(3, blogs.Count);
Assert.AreEqual("AAA", blogs[0].Name);
Assert.AreEqual("BBB", blogs[1].Name);
Assert.AreEqual("ZZZ", blogs[2].Name);
}
}
}
You can do this by mocking the DbSet.Add() method, like so:
[Fact]
public void CreateBlog_saves_a_blog_via_context()
{
var data = new List<Blog>
{
new Blog { Name = "BBB" },
new Blog { Name = "ZZZ" },
new Blog { Name = "AAA" },
};
var mockSet = new Mock<DbSet<Blog>>();
mockSet.Setup(blogs => blogs.Add(It.IsAny<Blog>)).Returns<Blog>(blog =>
{
data.Add(blog);
return blog;
});
var mockContext = new Mock<BloggingContext>();
mockContext.Setup(m => m.Blogs).Returns(mockSet.Object);
var service = new BlogService(mockContext.Object);
var blog = service.AddBlog("_ADO.NET Blog", "http://blogs.msdn.com/adonet");
var blogs = service.GetAllBlogs();
mockSet.Verify(m => m.Add(It.IsAny<Blog>()), Times.Once());
mockContext.Verify(m => m.SaveChanges(), Times.Once());
Assert.NotNull(blog)
Assert.Equal(4, blogs.Count);
Assert.Equal("AAA", blogs(1).Name);
Assert.Equal("BBB", blogs(2).Name);
Assert.Equal("ZZZ", blogs(3).Name);
}
This is adapted from the documentation found here.