loekd / servicefabric.mocks Goto Github PK
View Code? Open in Web Editor NEWServiceFabric.Mocks contains Mock classes to enable unit testing of Actors and Services
License: MIT License
ServiceFabric.Mocks contains Mock classes to enable unit testing of Actors and Services
License: MIT License
I does not know a way to test OnActivateAsync method via ServiceFabric.Mocks. Seems that it will be logical to invoke this protected method inside MockActorService.Activate.
It seems to be a timing thing, and maybe more than one call is trying to access the same entry at the same time, but they are all wrapped in transactions so I don't see why this should happen:
System.TimeoutException: The operation has timed out.
at ServiceFabric.Mocks.ReliableCollections.Lock1.<Acquire>d__11.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at ServiceFabric.Mocks.ReliableCollections.LockManager2.<AcquireLock>d__2.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()
at ServiceFabric.Mocks.ReliableCollections.TransactedConcurrentDictionary`2.d__26.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
further stack trace redacted
Hi Loek,
Do you see a way to mock the actor events?
I don't think it is possible because of the static class ActorProxyEventExtensions in Microsoft.ServiceFabric.Actors.Client?
When I call SubscribeAsync I get this exception:
System.ArgumentException: This method can only be called on ActorProxy.
Parameter name: actorProxy
at Microsoft.ServiceFabric.Actors.Client.ActorProxyEventExtensions.d__0`1.MoveNext()
Code to reproduce:
using System;
using System.Diagnostics;
using System.Fabric;
using System.Threading.Tasks;
using Microsoft.ServiceFabric.Actors;
using Microsoft.ServiceFabric.Actors.Client;
using Microsoft.ServiceFabric.Actors.Runtime;
using Microsoft.ServiceFabric.Data;
using Microsoft.ServiceFabric.Services.Remoting;
using Microsoft.ServiceFabric.Services.Runtime;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ServiceFabric.Mocks;
namespace Project.UnitTests
{
[TestClass]
public class ActorEventTests
{
protected static bool IsSuccess = false;
public interface IExampleEvents : IActorEvents
{
void OnSuccess(string msg);
}
public interface IExampleActor : IActor, IActorEventPublisher<IExampleEvents>
{
Task ActorSomething(string msg);
}
public class ExampleActorMock : Actor, IExampleActor
{
public ExampleActorMock(ActorService actorService, ActorId actorId) : base(actorService, actorId)
{
}
public Task ActorSomething(string msg)
{
Debug.WriteLine("Actor:"+msg);
var ev = GetEvent<IExampleEvents>();
ev.OnSuccess(msg);
return Task.CompletedTask;
}
}
public interface IExampleService : IService
{
Task DoSomething(Guid id, string msg);
}
public class ExampleClient : StatefulService, IExampleService, IExampleEvents
{
protected IActorProxyFactory ActorProxy;
public ExampleClient(StatefulServiceContext serviceContext) : base(serviceContext)
{
}
public ExampleClient(StatefulServiceContext serviceContext, IReliableStateManagerReplica reliableStateManagerReplica, IActorProxyFactory actorProxy) : base(serviceContext, reliableStateManagerReplica)
{
ActorProxy = actorProxy;
}
public async Task DoSomething(Guid id, string msg)
{
var proxy = ActorProxy.CreateActorProxy<IExampleActor>(new ActorId(id));
await proxy.SubscribeAsync<IExampleEvents>(this);
await proxy.ActorSomething(msg);
}
public void OnSuccess(string msg)
{
Debug.WriteLine("Service: "+msg);
IsSuccess = true;
}
}
[TestMethod]
public async Task TestSubscribeAsync()
{
var guid = Guid.NewGuid();
var id = new ActorId(guid);
Func<ActorService, ActorId, ActorBase> factory = (service, actorId) => new ExampleActorMock(service, actorId);
var svc = MockActorServiceFactory.CreateActorServiceForActor<ExampleActorMock>(factory);
var actor = svc.Activate(id);
var context = MockStatefulServiceContextFactory.Default;
var stateManager = new MockReliableStateManager();
var mockProxyFactory = new MockActorProxyFactory();
mockProxyFactory.RegisterActor(actor);
var exampleService = new ExampleClient(context, stateManager, mockProxyFactory);
await exampleService.DoSomething(guid, "message text");
Assert.IsTrue(IsSuccess);
}
}
}
Need support for netcoreapp2.0 and netstandard2.0
running on SF SDK 3.3.644
The repro example can be found here:
https://github.com/serpentfabric/Sf.Mocks.IssueRepro
Basically, if you set a reminder that doesn't repeat, let it expire, and attempt to unregister it, the real runtime throws an exception but sf.mocks continues without error
MockReliableConcurrentQueue.TryDequeueAsync does not return items if the supplied timeout is TimeSpan.Zero.
The ServiceFabric ReliableConcurrentQueue does allow a timeout of zero to return items if they exist (without blocking the queue to see if any arrive).
I think this is easily fixed on the following line, changing milliseconds > 0
to milliseconds >= 0
, which would allow a supplied timeout of 0 at least one iteration of the for
loop.
The code for CreateActor()
first configures an actor service with a factory method to create the actor (which new's up an instance of the actor class with the provided parameters) and thereafter it also new's up a new instance of the actor class, which it returns.
The reason for the two instantiation statements is not obvious. Very likely it is because I do not understand well enough the SF object lifetime management but my first impression is that I am confused regarding what the role of each new statement actually is. When is my actor created? Why does the other statement exist?
Some comments in the relevant code would be desirable, clarifying what the responsibilities of this code are in a mocking scenario and what the actual object flow is.
I have a unit test on a method that requires code in OnPreActorMethodAsync
to be called to work correctly. Is there a way to invoke actor instance methods in a way that this method is executed too?
I experienced deadlock issue in Tests specially when many tests sharing the Initialize I needed to synchronize the block to get it working :
Deadlock code to reproduce:
[TestInitialize]
public virtual async Task TestInitialize()
{
//await SyncLock.WaitAsync();
var partition = new MockStatefulServicePartition()
{
PartitionInfo = MockQueryPartitionFactory.CreateSingletonPartitonInfo(Guid.NewGuid())
};
this.VariantSettings = new Mock<IVariantSettings>(MockBehavior.Loose);
Func<StatefulServiceContext, IReliableStateManagerReplica2, TObj> serviceFactory =
(context, stateManagerReplica) =>
{
// The mock library creates a new partition per instance; re-create the StatefulServiceContext with our singleton partition.
context = MockStatefulServiceContextFactory.Create(
context.CodePackageActivationContext,
context.ServiceTypeName,
context.ServiceName,
partition.PartitionInfo.Id,
context.ReplicaId);
TObj service = this.CreateService(context, stateManagerReplica);
service.SetPartition(partition);
return service;
};
this.ReplicaSet = new MockStatefulServiceReplicaSet<TObj>(serviceFactory);
this.MockEventLogger = new Mock<IEventLogger>(MockBehavior.Loose);
this.CacheClient = new Mock<ICacheClient>(MockBehavior.Strict);
this.StoreResultCache = new Mock<IStoreResultCache<long>>(MockBehavior.Loose);
MockCodePackageActivationContext cxt =
(MockCodePackageActivationContext)this.ReplicaSet.CodePackageActivationContext;
cxt.ConfigurationPackage = GetTestConfiguration();
await this.ReplicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
await this.ReplicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);
this.Primary = this.ReplicaSet.Primary.ServiceInstance;
this.Secondary = this.ReplicaSet.FirstActiveSecondary.ServiceInstance;
//SyncLock.Release();
}
There are several dependency conflicts when using the latest Service Fabric package (6.5.641) with ServiceFabric.Mocks.
Hello,
I'm struggling with the ability to test multiple statefull services in my Unit tests. All tests work fine if they are executed seperately. But if the VSTS Test run Task executes them all together the task fails and shutdown unexpectedly. I think the issue resides on the ServiceFabric Mocks side since I'm using MockStatefulServiceContextFactory.Default. It doesn't help if I use the Create method of the factory for one of them. Could you please provide me some feedback about this or provide me with a workaround?
PS: we're running SF 2.5.216 so we are locked to 1.8.1 of the library.
Thanks!
I have an actor that is being tested via a mocked ActorService. When it tries to register a reminder, it encounters a NullReferenceException coming (based on stack trace information) from within the stateful storage system.
System.NullReferenceException : Object reference not set to an instance of an object.
Stack Trace:
at Microsoft.ServiceFabric.Actors.Runtime.KvsActorStateProvider.<AddOrUpdateReminderAsync>d__4c.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.<>c__DisplayClass1.<<ExecuteWithRetriesAsync>b__0>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.<ExecuteWithRetriesAsync>d__6`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Actors.Runtime.MockActorManager.<RegisterOrUpdateReminderAsync>d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.ServiceFabric.Actors.Runtime.ActorBase.<RegisterReminderAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
FileThingy\FileThingy.cs(109,0): at FileThingy.FileThingy.<TakeLeaseAsync>d__13.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
Tests\FileThingyTests.cs(51,0): at Tests.FileThingyTests.<TakeLease_TwiceInARow_RemembersLongestLease>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Using SF SDK 2.3.301 and ServiceFabric.Mocks 0.9.4.
This is the call that fails:
await RegisterReminderAsync(CleanupReminderName, null, durationFromNow, CleanupRetryInterval);
There is no actor state saved before this reminder registration call.
I am wanting to allow for the use of test spies in this framework so I can more easily make sure transactions are getting applied. On our team, a team member might forget to to commit a transaction on a ReliableDictionary<T>
and this override of a base test could help locate that issue faster.
So, what I'm wanting to commit a PR of something like below. Thoughts?
public class MockReliableStateManager : IReliableStateManagerReplica2
{
// ..begin methods
public virtual void Abort()
{
}
public virtual Task BackupAsync(Func<BackupInfo, CancellationToken, Task<bool>> backupCallback)
{
return BackupAsync(BackupOption.Full, TimeSpan.MaxValue, CancellationToken.None, backupCallback);
}
public virtual Task BackupAsync(BackupOption option, TimeSpan timeout, CancellationToken cancellationToken, Func<BackupInfo, CancellationToken, Task<bool>> backupCallback)
{
string stateBin = Path.Combine(Path.GetTempPath(), "state.bin");
using (var fs = File.Create(stateBin))
{
var formatter = new BinaryFormatter();
formatter.Serialize(fs, _store);
}
var info = new BackupInfo(Path.GetDirectoryName(stateBin), option, new BackupInfo.BackupVersion());
return backupCallback(info, CancellationToken.None);
}
public virtual Task ChangeRoleAsync(ReplicaRole newRole, CancellationToken cancellationToken)
{
ReplicaRole = newRole;
return Task.FromResult(true);
}
public virtual Task ClearAsync(ITransaction tx)
{
return ClearAsync();
}
public virtual Task ClearAsync()
{
_store.Clear();
return Task.FromResult(true);
}
public virtual Task CloseAsync(CancellationToken cancellationToken)
{
return Task.FromResult(true);
}
public virtual ITransaction CreateTransaction()
{
return new MockTransaction();
}
// other methods..
}
public class MockReliableStateManagerSpy : MockReliableStateManager
{
public MockTransactionSpy Transaction { get; private set; }
public bool TransanctionIsCreated => Transaction != null;
public bool TransactionIsCommitted => Transaction.IsCommitted;
public new ITransaction CreateTransaction()
{
Transaction = new MockTransactionSpy();
return Transaction;
}
}
public class MockTransactionSpy : MockTransaction
{
public bool IsCommitted { get; private set; }
private new Task CommitAsync()
{
IsCommitted = true;
return base.CommitAsync();
}
}
When creating a stateful actor an exception is thrown because the state provider is not mocked. First call to CreateActor in my test case throws an exception here:
System.Fabric.FabricRuntime.NativeFabricRuntimeFactory.GetCodePackageActivationContextHelper() C#
System.Fabric.Interop.Utility.WrapNativeSyncInvoke<System.__Canon>(func, functionTag, functionArgs) C#
System.Fabric.Interop.Utility.RunInMTA<System.Fabric.CodePackageActivationContext>(func) C#
Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.GetActorStateProviderOverride() C#
Microsoft.ServiceFabric.Actors.Runtime.ActorStateProviderHelper.CreateDefaultStateProvider(actorTypeInfo) C#
Microsoft.ServiceFabric.Actors.Runtime.ActorService.ActorService(context, actorTypeInfo, actorFactory, stateManagerFactory, stateProvider, settings) C#
ServiceFabric.Mocks.MockActorServiceFactory.CreateActorServiceForActor<Actors.Jobs.JobActor>(actorFactory) C#
Tests.Class1.CreateActor<Actors.Jobs.JobActor>(id) C#
Tests.Class1.CreateActor<Actors.Jobs.JobActor>(id) C#
Tests.Class1.Test() C#
Test class used:
public class Class1
{
internal static TActor CreateActor<TActor>(Guid id) where TActor : Actor
{
return CreateActor<TActor>(new ActorId(id));
}
internal static TActor CreateActor<TActor>(ActorId id) where TActor : Actor
{
Func<ActorService, ActorId, ActorBase> actorFactory = (service, actorId) => (ActorBase)Activator.CreateInstance(typeof(TActor), service, actorId);
var svc = MockActorServiceFactory.CreateActorServiceForActor<TActor>(actorFactory);
return actorFactory(svc, id) as TActor;
}
[Fact]
public async Task Test()
{
// new job
var job = CreateActor<JobActor>(Guid.NewGuid()) as IJobActor;
// new device
var device = CreateActor<DeviceActor>(Guid.NewGuid());
await job.Create(new Guid[] { Guid.NewGuid() }, new Guid[] { Guid.NewGuid() }, new IDeviceActor[] { device });
// new action
var action = CreateActor<JobActionActor>(Guid.NewGuid()) as IJobActionActor;
await action.Create(JobActionType.Download, new Uri[] { new Uri("http://test.net") });
await job.AddAction(action);
await job.Run();
}
}
var collection = await _stateManager.GetOrAddAsync<IReliableDictionary2<Guid, long>>("Collection");
using (var tx = _stateManager.CreateTransaction())
{
var query = await collection.CreateEnumerableAsync(tx, key => (Something that has no matches), EnumerationMode.Unordered);
var list = new List<Guid>();
This goes into infinite loop if the query returns an empty collection with a key value pair of null for both the key and the value.
while (await query.GetAsyncEnumerator().MoveNextAsync(new CancellationToken()))
list.Add(query.GetAsyncEnumerator().Current.Value.Id);
await tx.CommitAsync();
Thanks for this very nice library!
I'm writing a unit test which uses the MockReliableQueue. I expect that the message is still in the queue once the CommitAsync on the transaction is not called. But the message is removed.
Are there any plans to support transactions?
var queue = await StateManager.GetOrAddAsync<IReliableQueue<Message>>("QueueName");
using (var tx = StateManager.CreateTransaction())
{
var res = await queue.TryDequeueAsync(tx);
throw new Exception("Something went wrong");
// Remove from queue
await tx.CommitAsync();
}
Hi,
In MockStatefulServiceReplica th replica listeners are opened, before the role is set.
This resuls in no open listeners.
This is the change to fix the issue
This is the unit test that test the change:
MockStatefulServiceReplicaTests.txt
(I tried to push to a new branch to create a pull request but I get fatal error 403)
My actor service is accessing another actor service that belongs to a different application and is not in the same solution. The interface is known (referenced throw nuget package) but the implementation is not, so we cannot initiate it with its constructor, as it is done in the examples.
Is there a way to mock this accessed actor service with ServiceFabric.Mocks?
as expample, the AddStateAsync method in MockActorStateManager does not throw an InvalidOperationException if a state (key) already exists (in the dictionary). same for GetStateAsync.
can this be changed to throw the exceptions according to the real implementation?
Please add an example of how to create a mock for a StatefulSevice implementation that uses mocked partition information. The following code using reflection to try to set the Partition property does not work for the private setter for the StatefulServiceBase.Partition property because StatefulServicePartition does not implement IStatefulServicePartition (in 3.0.467)
var partitionInformation = MockQueryPartitionFactory.CreateIntPartitonInfo(0, 3, Guid.NewGuid());
Partition partition = MockQueryPartitionFactory.CreateStatefulPartition(partitionInformation, 1L, 1L, HealthState.Ok, ServicePartitionStatus.Ready, TimeSpan.MinValue, new Epoch());
var statefulServiceContext = CreateMockStatefulServiceContext(mockConfigurationPackage, partitionInformation);
this.sut = new MyStatefulService(
context: statefulServiceContext
);
PropertyInfo propertyInfo = this.sut.GetType().GetProperty("Partition", BindingFlags.Instance | BindingFlags.NonPublic, null, null, new Type[0], null);
propertyInfo.SetValue(this.sut, partition);
At a minimum, classes that implement IActorStateProvider need to account for the new IStateProviderReplica2 interface, and those that implement IServiceProxy need to provide ServicePartitionClient2 endpoint. Using statements related to remoting also need to be changed to include V1 specification.
A deeper assessment of V1 vs V2 probably also needs to happen to determine if the Mocks need to be extended or split to handle the new communication tooling.
How to mock a KeyedCollection during service initialization?
Currently you have to create a context and then set the collection before you can add to it
codePackageActivationContext.EndpointResourceDescriptions = keyedCollection;
if we added a default KeyedCollection like below we could add to it straight away.
public class EndpointResourceDescriptionsKeyedCollection : KeyedCollection<string, EndpointResourceDescription>
{
protected override string GetKeyForItem(EndpointResourceDescription item)
{
return item.Name;
}
}
Happy to submit a PR but wanted to pass it first.
My stateless service receives a parameter from the the ApplicationManifest.xml
and it is consumed at the constructor of the service.
I found
public class MockStatelessServiceContextFactory
{
public const string ServiceTypeName = "MockServiceType";
public const string ServiceName = "fabric:/MockApp/MockStatefulService";
public MockStatelessServiceContextFactory();
public static StatelessServiceContext Default { get; }
public static StatelessServiceContext Create(ICodePackageActivationContext codePackageActivationContext, string serviceTypeName, Uri serviceName, Guid partitionId, long instanceId);
}
but I haven't seen any sample on how to use this and more important, how to set the parameter required for my service to start.
Can you help?
When testing a StatefulService with your library, how do you make the RunAsync method start? I have a processing loop in RunAsync that consumes from a queue which I need to run and test its behavior.
Is there a method to call on the StatefulService/Context, or something similiar?
var context = MockStatefulServiceContextFactory.Default;
_stateManager = new MockReliableStateManager();
_mockThing = new MockThing{};
var service = new TenantDispatcherService(context, _stateManager, _mockThing);
service.??????
context.?????
In your example you create a mocked actor using the following lines:
Func<ActorService, ActorId, TActor> actorFactory = (service, actorId) => ...
var svc = MockActorServiceFactory.CreateActorServiceForActor<TActor>(actorFactory);
Actor = svc.Activate(id);
But how do I mock an actor which is using a custom ActorService? It´s initiated like this:
ActorRuntime.RegisterActorAsync<CompanyActor>(
(context, actorType) => new CustomActorService(context,
actorType,
(service, id) => new CompanyActor(service, id)))
.GetAwaiter().GetResult();
How can I supply an instance or mock of my CustomActorService type?
I am facing this issue when I run 100 task to update a counter, here is the attached test project to reproduce the issue.
TestSFMocksDeadLock.zip
Could you please add strong name to the nuget? We are using ServiceFabric.Mocks internally at Microsoft, but unsigned libraries cause all kinds of inconveniences. Thank you!
Please upgrade nuget package to the new sdk 2.6.204.
Are you planing to migrate to VS 2017?
I have a StatefulService that overrides RunAsync(CancellationToken token) with something like this:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
// Do some processing
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
}
}
Microsoft documentation states the following:
If an OperationCanceledException escapes from RunAsync(CancellationToken) and Service Fabric runtime has requested cancellation by signaling cancellationToken passed to RunAsync(CancellationToken), Service Fabric runtime handles this exception and considers it as graceful completion of RunAsync(CancellationToken).
When MockStatefulServiceReplica.DemoteToActiveSecondaryAsync() is called on a replica with a service that overrides RunAsync(..) as shown above, it throws an OperationCanceledException
with the message A task was canceled.
and the operation fails. I think DemoteToActiveSecondaryAsync()
should handle OperationCanceledException
s and disregard them.
To reproduce, add the RunAsync(..)
method above to StatefulServiceWithReplicaListener
and run test method TestPromoteActiveSecondaryToPrimaryAsync()
in the test project.
After upgrading the fabric version and this NuGet package, I am getting the following error in VSTS builds:
Could not load type 'Microsoft.ServiceFabric.Data.Collections.IReliableConcurrentQueue1' from assembly 'Microsoft.ServiceFabric.Data.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Stack Trace: at ServiceFabric.Mocks.MockReliableStateManager.<>c__DisplayClass25_0
1.b__0(Uri collectionName)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func
2 valueFactory)
at ServiceFabric.Mocks.MockReliableStateManager.GetOrAddAsync[T](ITransaction tx, String name)
It runs fine locally, so I am just looking for any pointers on what could be wrong in the hosted build.
Readme says:
3.1.0
Upgraded nuget packages (SF 2.8.232)
But nuget doesn't agree https://www.nuget.org/packages/ServiceFabric.Mocks/
Hi ,
There is no package available which points to the Service fabric packages for version 3.3.622
When using ServiceFabric.Mocks to version 3.4.3 which should support all version of service fabric greated than 3.2.187, I am getting error "System.TypeLoadException : Method 'CreateNonIServiceProxy' in type 'ServiceFabric.Mocks.MockServiceProxyFactory' from assembly 'ServiceFabric.Mocks, Version=3.4.3.0, Culture=neutral, PublicKeyToken=c8a3b3cecf8974ee' does not have an implementation"
Version 3.4.5 of the Mocks supports 3.3.624, which seems to have been deprecated by microsoft. Could you suggest which version of Mock should we use if we are using version 3.3.622 for service fabric
In your Tests project, you have the following Test:
[TestMethod]
public async Task TestServiceState_InMemoryState_PromoteActiveSecondary()
{
var replicaSet = new MockStatefulServiceReplicaSet<MyStatefulService>(CreateStatefulService, CreateStateManagerReplica);
await replicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
await replicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);
await replicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 3);
const string stateName = "test";
var payload = new Payload(StatePayload);
//insert data
await replicaSet.Primary.ServiceInstance.InsertAsync(stateName, payload);
//promote one of the secondaries to primary
await replicaSet.PromoteActiveSecondaryToPrimaryAsync(2);
//get data
var payloads = (await replicaSet.Primary.ServiceInstance.GetPayloadsAsync()).ToList();
//data should match what was inserted against the primary
Assert.IsTrue(payloads.Count == 1);
Assert.IsTrue(payloads[0].Content == payload.Content);
//the primary should not have any in-memory state
var payloadsFromOldPrimary = await replicaSet[1].ServiceInstance.GetPayloadsAsync();
Assert.IsTrue(!payloadsFromOldPrimary.Any());
}
The problem is this test is not working, if service is executing endless loop in RunAsync, let's say for background task.
Some details:
AddReplicaAsync will wait for CreateAsync:
public async Task AddReplicaAsync(ReplicaRole role, long? replicaId = null, int activationDelayMs = 0)
{
var serviceContext = MockStatefulServiceContextFactory.Create(CodePackageActivationContext, ServiceTypeName, ServiceUri, Guid.NewGuid(), replicaId ?? _random.Next());
var stateManager = _stateManagerFactory(serviceContext, _reliableStates);
var replica = new MockStatefulServiceReplica<TStatefulService>(_serviceFactory, serviceContext, stateManager);
await replica.CreateAsync(role);
_replicas.Add(replica);
}
and then CreateAsync will wait for RunAsync which will never return
public async Task CreateAsync(ReplicaRole role)
{
await OpenAsync(ReplicaOpenMode.New);
if (role == ReplicaRole.Primary)
{
await OpenServiceReplicaListeners();
await ChangeRoleAsync(role);
await RunAsync();
}
else
await ChangeRoleAsync(role);
}
My suggestion is to wait for RunAnync to be completed in CreateAsync. Thank you.
Some of my unit tests appear to behave significantly differently when run against mocks vs real storage when more than one thread is accessing the reliable storage.
It would be great if the mocks also mocked the synchronization model of the real objects.
(reported through nuget)
We're using Service Fabric mocks heavily for our unit testing of Service Fabric reliable services. Before all, thank you and your team for this library.
I'd like to report an issue with ServiceFabric.Mocks.ReliableCollections.MockReliableQueue though. The implementation behaves in a way that breaks IReliableQueue contract in multiple ways. Let me explain with an example.
Say a queue has the items: A B C D E If you: await queue.TryDequeueAsync(tx); await queue.TryDequeueAsync(tx); await queue.TryDequeueAsync(tx); tx.Abort(); you will end up with the following state in the queue: D E C B A instead of A B C D E
It enqueues the dequeued items that were aborted back into the queue, that basically puts them to the tail instead of the head
It reversed the order while doing so
This behavior greatly reduces the usability of MockReliableQueue. Can you please let me know whether you would have this fixed or not. If so, how long would it take to get the fix?
We'd like to be able to test our logic that kicks in during SF role transitions.
The following sequence of operations yields an error though:
this.ReplicaSet = new MockStatefulServiceReplicaSet(serviceFactory);
…
await this.ReplicaSet.AddReplicaAsync(ReplicaRole.Primary, 1);
await this.ReplicaSet.AddReplicaAsync(ReplicaRole.ActiveSecondary, 2);
...
await this.ReplicaSet.PromoteActiveSecondaryToPrimaryAsync(2);
When added, the last step fails with the following error:
System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.ServiceFabric.FabricTransport, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies.
When FabricTransport dll reference is added, it fails with the following error:
System.Runtime.InteropServices.COMException: No such host is known. (Exception from HRESULT: 0x80072AF9).
That is, it seems to actually try and use the real transport, not a mock one.
What is the way to enable promotion and demotion of replicas to different roles using mock library?
Thanks,
-Ayse
when i want to verify my actor is removing an existing reminder, i first need to call
GetReminder( String reminderName )
to obtain the IActorReminder by name. unfortunately this throws a ReminderNotFoundException.
as far as i can see, this method does not even touch the mock state provider.
if this is the wrong approch to test unregistering a reminder, what would be the right way?
It's perfectly valid to do something like this:
var actorId = new ActorId(some_guid);
var actor_1 = _actorProxyFactory.CreateActorProxy<IMyActorType>(actorId);
var actor_2 = _actorProxyFactory.CreateActorProxy<IMyOtherActorType>(actorId);
but MockActorProxyFactory
expects a single instance of IActor
for each ActorId
and so this scenario can't be mocked.
Hi,
I notice in my test, when multiple threads sets content to the same reliable connect. They deadlock and hang there. It makes multi-thread testing hard.
It appears VSTS 2017 hosted build agents recently had SF SDK 2.7 preview installed, breaking our Unit Tests that use ServiceFabric.Mocks:
System.TypeLoadException: Method 'Initialize' in type 'ServiceFabric.Mocks.MockActorStateProvider' from assembly 'ServiceFabric.Mocks, Version=1.8.1.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
Any chance of creating a prerelease based on SDK 2.7 preview?
I am willing to create a PR, but some guidance may be needed since I am not very active in OS.
Per the documentation of IReliableDictionary
Summary:
Adds a key/value pair to the Reliable Dictionary if the key does not already exist, or updates a key/value pair in the Reliable Dictionary if the key already exists.
However, looks like the mock is implemented to throw if the key does not exist, this deviates from the Service fabric implementation
This issue only occurs while testing service moves using the new MockStatefulServiceReplicaSet.
When a stateful service primary moves to a new replica that was not originally part of the replica set, the rebuild event is triggered. This is the behavior we observed while our service is running on the cluster. However, this condition is not documented very thoroughly on the ASF docs.
Currently, I do not believe rebuild events are being emitted from the MockReliableStateManager
under this condition. This is because we have to share the same instance of the MockReliableStateManager
for all replicas to simulate the replicas' state keeping in state with each other. The trade off is the MockReliableStateManager
cant track the role for the specific replica hosting its instance. We would need this to be able to know when the replica is transitioning from Unknown -> Idle/Active Secondary. This transition is when the state manager's rebuild event is triggered.
The rebuild i believe is to allow a new replica to subscribe to all reliable states currently being managed by the replica set as it comes into the fold. Without this, the new node will not be able to subscribe to events like DictionaryChanged.
I believe the first part to allowing the simulation of this event is to allow for different State manager instances to be inserted into each replica. This will allow the state manager to observe the role of its owning replica. That will then allow it to trigger events during the role transitions.
The second part of the solution is how to keep the State manager instances in sync with each other. To do this I believe there are two options. First, we inject into the state manager or the mock reliable states a singleton dictionary so that all the state managers save their data to a single location. The drawback to this solution is it makes the creation of the MockReliableStateManager
much more complex. It puts more burden on the consumers of this package. The other option would be to add some sort of eventing between the state manager instances to simulate them staying in sync.
I wanted to get some input on whether to use injection of single dictionaries or events before i push a PR with a change to support this.
The MockActorStateManager throws exception when try to call TryGetStateAsync with a generic type ValueType and StateManager doesn't contains the key.
I clone the repository and I fix the issue.
Can I authorize to pull request?
Max
When I want to mock the following code in an actor:
await StateManager.SetStateAsync(stateName, string.Empty);
await StateManager.SetStateAsync(stateName, 5);
await StateManager.SetStateAsync(stateName, DateTimeOffset.UtcNow);
It fails with an InvalidCastException
trying to cast 5 to string. It is actually valid code when running under Service Fabric itself.
If you agree, I can create a PR to fix this.
Could you please add strong name to the nuget?
We are using ServiceFabric.Mocks internally at Microsoft, but unsigned libraries cause all kinds of inconveniences. Thank you!
Hi,
I am trying to do some very basic unit tests around my SchedulerActor
but I cannot get that working.
private static SchedulerActor CreateActor(ActorId id)
{
Func<ActorService, ActorId, ActorBase> actorFactory = (service, actorId) => new SchedulerActor(service, id);
var svc = MockActorServiceFactory.CreateActorServiceForActor<SchedulerActor>(actorFactory);
var actor = svc.Activate(id);
return actor;
}
The exception message:
System.TypeInitializationException : The type initializer for 'ServiceFabric.Mocks.MockStatefulServiceContextFactory' threw an exception.
----> System.TypeLoadException : Method 'ReportApplicationHealth' in type 'ServiceFabric.Mocks.MockCodePackageActivationContext' from assembly 'ServiceFabric.Mocks, Version=2.1.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
at ServiceFabric.Mocks.MockActorServiceFactory.CreateActorServiceForActor[TActor](Func`3 actorFactory, IActorStateProvider actorStateProvider, StatefulServiceContext context, ActorServiceSettings settings)
I have started using ServiceFabric.Mocks for mocking, I am testing a scenario where ACtor is called from a service, more specifically an API, which is .net core stateless service. Actor is being called from controller and I am writing unit tests for controller, I am mocking the Actor using mockActorProxyFactory, in the tests i get a correct instance of mockActorProxyFactory with all mocked data, but when in controller it tries to createActor proxy it returns always null
ActorProxyFactory.CreateActorProxy(new ActorId(Id)) This line is always returning me null.
do we have a any such issue which is known, I am using 3.4.5 version of mocks and 3.4.624 version of service fabric.
Any help will be appreciated!
I am using the details given in link for Communication between Actors and Services
https://loekd.wordpress.com/2018/03/05/unit-testing-in-azure-service-fabric/
Line 52 of ServiceFabric.Mocks/ReliableCollections/MockReliableDictionary.cs shows that the function is not implemented
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.