OrleansTestKit icon indicating copy to clipboard operation
OrleansTestKit copied to clipboard

How to unit test GrainService

Open mgendre opened this issue 5 years ago • 4 comments

Hello,

First, thank you for your amazing work !

I would like to know if it's possible to unit test GrainService using something like TestKitBase. Is it possible to do it without creating a TestCluster ?

Thank you in advance,

mgendre avatar Oct 31 '19 15:10 mgendre

The TestKit does not currently support GrainServices, only Grains. Perusing the abstract GrainService class and its base, abstract SystemTarget class, I'm not exactly sure what the TestKit could/would provide to assist with testing.

Do you have an example GrainService to share with some use cases to highlight?

seniorquico avatar Oct 31 '19 18:10 seniorquico

Thank you for your reply,

We have a GrainService that is called on RX events subscription from a third party application, so it should runs on all silos in order to support redondancy. We choose GrainService to achieve that.

The service is a bit complex and calls internally several grains. Because this service is the entry point, we would like to unit test it and also inject mocked grains inside of it.

The GrainService requires few parameters, like the silo. You made that easier with your framework for the grains. It may be great that this test framework make GrainService instantiation easier. I didn't have found a way to get the Silo instance from the unit tests.

mgendre avatar Nov 04 '19 11:11 mgendre

We do not provide a mock Silo (the TestKitSilo is a misnomer... it doesn't extend Silo or correlate to anything in the Orleans framework). I'd recommend testing GrainServices via TestCluster. However, if you are able to build an example, we could discuss strategies and what, if anything, may be possible with the TestKit.

seniorquico avatar Nov 05 '19 23:11 seniorquico

Here is an example of what I try to achieve:

public class SampleTest : TestKitBase
    {
        [Fact]
        public async Task TestMyGrainService()
        {
            var sampleGrainMock = Silo.AddProbe<ISampleGrain>(0);
            
            // How to use TestKit to help me to create a new MyGrainService ?
            var serviceToTest = new MyGrainService(null, null, null, null);
            // For example we have following method to create grain:
            // Silo.CreateGrainAsync<SampleGrain>(0).Result;
            
            await serviceToTest.DoTheJob();
            
            sampleGrainMock.Verify(x => x.AnotherMethod(), Times.Once);
        }
    }

    public class MyGrainService : GrainService, IMyGrainService
    {
        private readonly IGrainFactory _grainFactory;

        public MyGrainService(
            IGrainIdentity grainId,
            Silo silo,
            ILoggerFactory loggerFactory,
            IGrainFactory grainFactory) : base(grainId, silo, loggerFactory)
        {
            _grainFactory = grainFactory;
        }

        public Task DoTheJob()
        {
            // Service stuff ...

            // Call another grain from this service
            return _grainFactory.GetGrain<ISampleGrain>(0).AnotherMethod();
        }
    }

    public interface ISampleGrain : IGrainWithIntegerKey
    {
        Task AnotherMethod();
    }

    public interface IMyGrainService : IGrainService
    {
        Task DoTheJob();
    }
}

Tell me if you need more

mgendre avatar Nov 07 '19 08:11 mgendre