Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mocking grain interfaces returned from AsReference for unit testing #9257

Open
TimoSchmechel opened this issue Dec 2, 2024 · 0 comments
Open

Comments

@TimoSchmechel
Copy link

TimoSchmechel commented Dec 2, 2024

When writing unit tests for a class that performs some grain calls its currently impossible if the extension method AsReference is used.
This problem doesnt arise when just using GetGrain to access the grain as there we can easily return a mocked version of the grain interface.

Ideally I would like to be able to unit test services that rely on grain calls easily without having to use an in memory cluster or any other complicated mock setups. The fact orleans relies on interfaces makes this very easy except for when relying on AsReference casts to get an IAddressable.

Below is a simple example that demonstrates the problem

[TestFixture]
public class UnitTestExample
{
    [Test]
    public async Task GrainMocking()
    {
        var fixture = new Fixture();

        var sut = fixture.Create<IExampleService>();

        var result = await sut.MethodWithGrainCall();

        result.Should().NotBeNull();
    }
    
    [Test]
    public async Task AddressableMocking()
    {
        var fixture = new Fixture();

        var sut = fixture.Create<IExampleService>();

        //this fails
        var result = await sut.MethodWithGrainCallViaAsReference();

        result.Should().NotBeNull();
    }
}

public interface IExampleService
{
    Task<string> MethodWithGrainCall();
    Task<string> MethodWithGrainCallViaAsReference();
}

class ExampleService : IExampleService
{
    private IGrainFactory _grainFactory;

    public ExampleService(IGrainFactory grainFactory)
    {
        _grainFactory = grainFactory;
    }

    public async Task<string> MethodWithGrainCall()
    {
        var grain = _grainFactory.GetGrain<IExampleGrain>(0);

        var grainResult = await grain.GetString();

        return grainResult;
    }
    
    public async Task<string> MethodWithGrainCallViaAsReference()
    {
        var grain = _grainFactory.GetGrain<IExampleGrain>(0).AsReference<IExampleAddressable>();

        var grainResult = await grain.GetStringAsAddressable();

        return grainResult;
    }
}

internal interface IExampleAddressable : IAddressable
{
    Task<string> GetStringAsAddressable();
}

internal interface IExampleGrain : IGrainWithIntegerKey
{
    Task<string> GetString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant