Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown when Unit Testing Xamarin.Forms app - c#

I am running Unit Tests for my Xamarin.Forms application, and the Unit Tests throw Xamarin.Essentials.NotImplementedInReferenceAssemblyException:
I have created a Unit Test project for the app (using NUnit 3.12.0) and have written the below code to test the functionality.
[TestFixture()]
public class Test
{
[Test()]
public void TestCase()
{
AutoResetEvent autoEvent = new AutoResetEvent(true);
SomeClass someClass = new SomeClass();
someClass.SomeFunction((response) =>
{
Assert.AreEqual(response, "Hello")
autoEvent.Set();
});
autoEvent.WaitOne(); //** Xamarin.Essentials.NotImplementedInReferenceAssemblyException thrown here**
}
}
Below is the code under test from the Xamarin.Forms app:
public class SomeClass
{
public void SomeFunction(Action<string> callback)
{
// asynchronous code...
callback("Hello");
}
}
The above functionality works fine in the Xamarin.Forms app.
Note: I read that await/async can be used, however, I will have to make changes in the entire project. This is not a feasible solution for now.
Edit 1:
I have created a sample Xamarin.Forms project with Unit Tests in it. The project is available here

You need to add the Xamarin.Essentials NuGet Package to your Unit Test Project.
I highly recommend using Dependency Injection + Xamarin.Essentials.Interfaces, because certain Xamarin.Essentials APIs aren't implemented on .NET Core and you'll need to create your own implementation.
For example, here are some of the Xamarin.Essentials APIs I implemented in .NET Core for Unit Testing my GitTrends app:
AppInfo
Browser
DeviceInfo
Email
FileSystem
Launcher
MainThread
Preferences
SecureStorage
VersionTracking

While you have stated that the subject function cannot be made async at this time, the test however can be made async.
TaskCompletionSource can be used to wait for the callback to be invoked.
[TestFixture()]
public class Test {
[Test()]
public async Task TestCase() {
//Arrange
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
Action<string> callback = (arg) => {
tcs.TrySetResult(arg);
};
SomeClass someClass = new SomeClass();
//Act
someClass.SomeFunction(callback);
string response = await tcs.Task;
//Assert
Assert.AreEqual(response, "Hello")
}
}

The issue can be related to what exactly the call back is trying to do. For example the Connectivity function of Xamarin.Essentials won't work (and will throw that type of exception) if you are calling it from your unit test as it is not running on a mobile platform and thus doesn't have that feature implemented.
A solution to this, at least one I've done for that type of functionality, is to create an interface. So, to continue with the example above regarding the Connectivity feature we can do this:
Make an interface
public interface IConnectivityService {
bool CanConnect()
}
Define both an actual implementation of it that will be used during the app running, and one for testing purposes
public ConnectivityService : IConnectivityService {
//implement the method
}
public ConnectivtyServiceMock : IConnectivityService {
//implement the method, but this is a mock, so it can be very skinny
}
Update your View/VM to accept this interface, and inside of the test case instantiate the mock version of it and pass that in.
In such scenarios where we have to reference device specific implementations from a unit test, we have to abstract it away in an interface and use that implementation instead

I checked your code and it is not throwing any Xamarin.Essentials exception. To run the unit test, I had to add the "NUnit3TestAdapter" nuget package.
You will have to wait for callback otherwise test will crash. You can use TaskCompletionSource suggested by #Nkosi.
[Test()]
public async Task TestCase()
{
XamarinMock.Init();
WebApi webApi = new WebApi();
TaskCompletionSource<HttpResponseMessage> tcs = new TaskCompletionSource<HttpResponseMessage>();
Action<HttpResponseMessage> callback = (arg) => {
tcs.TrySetResult(arg);
};
webApi.Execute(callback);
var response = await tcs.Task;
Console.WriteLine(response);
Assert.AreEqual(response.StatusCode, HttpStatusCode.OK);
}

Related

xUnit Theory with async MemberData

I have a unit test project using xUnit.net v.2.3.1 for my ASP.NET Core 2.0 web app.
My test should focus on testing a given DataEntry instance: DataEntry instances are generated by the async method GenerateData() in my DataService class, which looks like:
public class DataService {
...
public async Task<List<DataEntry>> GenerateData() {
...
}
...
}
I am writing this test case as a Theory so my test can focus on a DataEntry instance at a time. Here is the code:
[Theory]
[MemberData(nameof(GetDataEntries))]
public void Test_DataEntry(DataEntry entry) {
// my assertions
Assert.NotNull(entry);
...
}
public static async Task<IEnumerable<object[]>> GetDataEntries() {
var service = new DataService();
List<DataEntry> entries = await service.GenerateData().ConfigureAwait(false);
return entries.Select(e => new object[] { e });
}
However, I get the following error at compile time:
MemberData must reference a data type assignable to 'System.Collections.Generic.IEnumerable<object[]>'. The referenced type 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<object[]>>' is not valid.
From the error description, it seems xUnit.net does not allow MemberData to use an async static method, like my GetDataEntries() one. Is there any functionality gap in xUnit.net I should be aware of?
Now, I know I could switch my Theory into a Fact and loop through each DataEntry in the list returned by my DataService, however I would prefer to keep a Theory setup as my test would be cleaner and focused on DataEntry instead of List<DataEntry>.
Question: is there any way in xUnit.net to let my Theory get data from my DataService async API? Please, note the DataService class cannot be changed nor extended to provide data synchronously.
EDIT
I am looking for a way through async/await and would prefer to avoid any usage of blocking calls such as Task<T>.Result e.g. on my GenerateData() method, as the underlying thread will be blocked til the operation completes.
This is relevant in my test project as I have other similar test cases where data should be retrieved in the same way and therefore I want to avoid ending up with too many blocking calls, but instead keeping the async/await propagation.
Until xUnit allows async theory data, you can use Task<T> instances as theory data and await them inside the test method (note that test methods can be async):
public static IEnumerable<object> GetDataEntries() {
var service = new DataService();
yield return new object[] { service.GenerateData() };
}
[Theory]
[MemberData(nameof(GetDataEntries))]
public async Task Test_DataEntry(Task<List<DataEntry>> task) {
List<DataEntry> entries = await task;
for (int i = 0; i < entries.Count; i++) {
// my assertions
Assert.NotNull(entries[i]);
}
}
This functionality is not provided internally. You can try following:
Write your CustomMemberDataAttribute by inheriting DataAttribute.
Override 'GetData' method of parent class.
Make the method async, that, provides data.
Call async data provider method from 'GetData' method.
Use your CustomMemberDataAttribute to decorate test cases.
You can refer following link to write your custom attribute.
Keep other method same, just modify 'GetData' method as discuss above.
https://github.com/xunit/xunit/blob/bccfcccf26b2c63c90573fe1a17e6572882ef39c/src/xunit.core/MemberDataAttributeBase.cs

Testing MassTransit Subsciber

I need to test my subscriber which is using MassTransit.
Below is a sample code :
using System;
using MassTransit;
public class AnimalSubscriber : Consumes<Animal>.Context
{
public void Consume(IConsumeContext<Animal> message)
{
//.. my code here..
}
}
Right now I have not Idea how to test the Subscriber. If someone could let me know some details; that would be very helpful!
As of now, foolishly I thought of creating a Object of AnimalSubscriber and call the Consume method.
[TestFixture]
public class Test
{
[Test]
public void SearchAnimals()
{
AnimalSubscriber subscriber = new AnimalSubscriber();
Animal request = new Animal
{
Id : 1,
Name : "Tiger"
};
//Not sure how to mock this IReceiveContext.
IReceiveContext context = new ReceiveContext();
IConsumeContext<Animal> message =new ConsumeContext<Animal>(context, request);
subscriber.Consume(null);
}
}
But I got stuck with the below line of code :
IConsumeContext<Animal> message =new ConsumeContext<Animal>(context, request); //<- Not sure how to mock this IReceiveContext.
Error : The type 'MassTransit.Context.ReceiveContext' has no
constructors defined
Need some advice please!
If you are using MassTransit v2 (which based on the interfaces you've specified above is indeed the case), you can use the Testing namespace to build out your tests.
An example unit test is available in the v2 repository branch: https://github.com/MassTransit/MassTransit/blob/v2-master/src/MassTransit.Tests/Testing/ConsumerTest_Specs.cs#L19
As an example, a testing fixture can be setup to build your consumer and send messages to it:
_test = TestFactory.ForConsumer<AnimalSubscriber>()
.InSingleBusScenario()
.New(x =>
{
x.ConstructUsing(() => new AnimalSubscriber());
x.Send(new Animal(), (scenario, context) => context.SendResponseTo(scenario.Bus));
});
_test.Execute();
Then you can build assertions around that test, such as:
_test.Sent.Any<A>().ShouldBeTrue();
Note that this only works with v2, the Testing namespace, while present in v3, doesn't exactly work yet (it didn't survive the move to async and I haven't taken the time to get it entirely working yet).

Test view model with WCF service calls

I want to unit test my view model which makes wcf service calls.
My view model:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
});
}
}
My service client interface:
public interface IService
{
void LoadThisAndThat(EventHandler<ThisAndThatCompletedArgs> callback);
}
This is implemented by a class which uses the actual generated service client proxy to make the call.
My question is: How can I unit test, that my view model does the service call and fills my collections with returned data?
To expand on Sheridan's answer - what are you trying to test?
The network connection?
The service frameworking (e.g. WCF)?
The .NET implementation of threads?
I'm guessing that all you are really interested in is how your view model responds to the data it is provided by the service. Let us slightly re-factor your code to make this more transparent (all we have really done it to remove the EventHandler delegate from the signature of the service method):
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load()
{
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t =>
{
//Fill collections and so on
});
}
}
public interface IService
{
Result GetResult();
}
Does this answer your question? No!
Even if you were to mock out the implementation of IService, the .NET implementation of threads does not guarantee anything about when the call to service.GetResult() will run, or when the results will be returned back to view model. However - are we interested in testing the .NET threading implementation? I guess not.
If you are dedicated to testing, then you have to consider the tests as first-class consumers of your code. To this end we have to modify our code to make it more amenable for testing. Take two is below:
public class FooViewModel : Screen
{
private IService service;
public FooViewModel(IService service)
{
this.service = service;
}
public void Load(bool runAync = true)
{
if (runAync)
Task.Factory.StartNew(() => service.GetResult())
.ContinueWith(t => SetResults(t.Result));
else SetResults(service.GetResult());
}
private void SetResults(Result result)
{
//Fill collections and so on
}
}
Here we have introduced a boolean parameter to the Load() method, which will default to true. During testing, we call it with false to ensure the results are dealt with synchronously and our view model is behaving as we would expect with the data returned.
If you don't like the addition of the extra parameter, you could just make the SetResults method public, and treat that as your initialization step during testing.
The takeaway is that we shouldn't be afraid to make changes to the public implementation to accommodate testing.
Simply implement a method that returns some data in your TestService class. The purpose is not to test whether the WCF service works, but to test how the view model works. As such, we create a situation which appears as if the service is working perfectly... we simply return the required data, but without needing to call the actual service which is one of the main things that we are trying to avoid.
the problem here is that the callback is called asynchronously.
the callback pattern is outdated, use Task !
you can do
public Task<int> Load()
{
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
service.LoadThisAndThat((o,e) =>
{
//Fill collections and so on
source.SetResult(e.Count);
});
return source.Task;
}
so that in your test you could do (synchronously)
public void test()
{
var result=Load().Result;
}
Tasks are good for many many things !

Decent pattern for testable async operations?

I had trouble finding a simple, flexible pattern to allow me to write code in my ViewModels that in runtime would run asynchronously but during test-time run synchronously. This is what I came up with - does anyone have any suggestions? Is this a good path to go down? Are there better existing patterns out there?
LongRunningCall definition:
public class LongRunningCall
{
public Action ExecuteAction { get; set; }
public Action PostExecuteAction { get; set; }
public LongRunningCall(Action executeAction = null, Action postExecuteAction = null)
{
ExecuteAction = executeAction;
PostExecuteAction = postExecuteAction;
}
public void Execute(Action<Exception> onError)
{
try
{
ExecuteAction();
PostExecuteAction();
}
catch (Exception ex)
{
if (onError == null)
throw;
onError(ex);
}
}
public void ExecuteAsync(TaskScheduler scheduler, Action<Exception> onError)
{
var executeTask = Task.Factory.StartNew(ExecuteAction);
var postExecuteTask = executeTask.ContinueWith((t) =>
{
if (t.Exception != null)
throw t.Exception;
PostExecuteAction();
}, scheduler);
if (onError != null)
postExecuteTask.ContinueWith((t) => { onError(t.Exception); });
}
}
Usage:
var continueCall = new LongRunningCall(continueCommand_Execute, continueCommand_PostExecute);
if (svc.IsAsyncRequired)
continueCall.ExecuteAsync(TaskScheduler.FromCurrentSynchronizationContext(), continueCommand_Error);
else
continueCall.Execute(continueCommand_Error);
The only real pre-requisite is that you need to know at runtime if you're supposed to use async/sync. When I run my unit tests I send in a mock that tells my code to run synchronously, when the application actually runs IsAsyncRequired defaults to true;
Feedback?
I would prefer to encapsulate the decision on whether to execute code synchronously or asynchronously in a separate class that can be abstracted behind an interface such as this:
public interface ITaskExecuter
{
void ScheduleTask(
Action executeAction,
Action postExecuteAction,
Action<Exception> onException);
}
An instance of a class implementing ITaskExecuter can be injected where required.
You can inject different instances for testing versus production scenarios.
Usage becomes:
taskExecuter.ScheduleTask(
continueCommand_Execute,
continueCommand_PostExecute,
continueCommand_Error);
with no separate code paths in the calling class for test versus production.
You have the option of writing tests that:
just check the correct actions are passed to the task executer, or
configuring the task executer to execute the action synchronously and
test for the desired result, or
do both.
I did something very simmilar at my current job, but can't get to the code to copy/paste it right now...
Basically what I did was to create an IWorker interface, with a DoWork(Func<>) method.
Then I created 2 derived classes, one 'AsyncWorker' and one 'SyncWorker'. The SyncWorker just executes the passed in Func (synchronously), and the 'AsyncWorker' is a wrapper around a BackgroundWorker that sends the passed in Func off to the BackgroundWorker to be processed asynchronously.
Then, I changed my ViewModel to have an IWorker passed in. This moves the dependency resolution out of the ViewModel, so you can use a Dep. Inj. utility (I use Unity and Constructor injection).
Since I use Unity, in my unit test configuration, I then map IWorker to SyncWorker, and in production I map IWorker to AsyncWorker.
Hope that makes sense... I know it'd be easier if I had the code on hand...
Consider changing ExecuteAsync so that it will return a Task:
public Task ExecuteAsync(TaskScheduler scheduler, Action<Exception> onError)
So in production code, I would just call it as is:
longRunningCall.ExecuteAsync(
TaskScheduler.FromCurrentSynchronizationContext(),
continueCommand_Error);
But in unit tests, I would wait for the task to actually finish:
var task = longRunningCall.ExecuteAsync(
TaskScheduler.FromCurrentSynchronizationContext(),
continueCommand_Error);
task.Wait();

Creating a mock API for third party library in statically typed language?

I have an application in VB/C# .NET which needs to interact with a third party API, but I would like to interface it out so I can use a mock API for testing purposes. Here are example API calls I would use in code:
RelayClient.AuthenticateUser(username, password, request, sessionID)
RelayClient.GetUserInfo(sessionID)
A few problems I am facing:
RelayClient is NonInheritable/Static.
RelayClient doesn't implement any interfaces.
The API client library is closed source.
Is there any standard way of dealing with this situation?
The way to do this would be to make your code work against 'middle-man' non-static classes, which internally use the static classes from your 3rd party API. You then mock out these 'middle-man' classes for your unit tests.
Something like... (untested code)
// your consuming class
public class MyClass
{
private readonly RelayClientManager manager;
public MyClass(RelayClientManager manager)
{
this.manager = manager;
}
public UserInfo GetUserInfo(int sessionID)
{
return manager.GetUserInfo(sessionID);
}
}
// 'middle-man' class
public class RelayClientManager
{
public UserInfo GetUserInfo(int sessionID)
{
return RelayClient.GetUserInfo(sessionID);
}
}
// unit test (using xUnit.net and Moq)
[Fact]
public static void GetsUserInfo()
{
// arrange
var expected = new UserInfo();
var manager = new Mock<RelayClientManager>();
manager.Setup(x => x.GetUserInfo(0)).Returns(expected);
var target = new MyClass(manager);
// act
var actual = target.GetUserInfo(0);
// assert
Assert.Equal(expected, actual);
}
If you don't want to roll your own abstraction, have a look at TypeMock Isolator- it uses profiler hooks to do runtime class-level mocking of pretty much anything, whether you own it or not. It actually does a runtime substitution of the type implementation and intercepts all the calls (eg, you don't need to subclass the type- as far as the CLR is concerned, you ARE the type).
It's commercial, but they do have a free trial. Depending on how big the thing you need to mock is, the $799 can be well worth the time abstracting/wrapping the entire API surface if it's not interface-based.

Categories

Resources