0

Moq:

var someService = new Mock<ISomeService>();
var data = new ...;

someService.Setup(x => x.UpdateAsync(It.IsAny<Action<OneClass, TwoClass>>()))
    .Callback<Action<OneClass, TwoClass>>((func) =>
    {
        func(data);
    })
    .Returns(Task.CompletedTask);

UpdateAsync have action (first parameter).

I want to execute action.

I tried

someService
    .UpdateAsync(Arg.Do<Action<OneClass, TwoClass>>(x => x(data)))
    .Returns(Task.CompletedTask);

but it didn`t work.

How is this done using NSubstitute?

Nkosi
  • 235,767
  • 35
  • 427
  • 472
gen32
  • 11
  • 3
  • `it is not working` is a rather broad statement. It does not tell us what is actually happening as apposed to what was expected. – Nkosi Feb 06 '20 at 15:04
  • You have an action that takes two arguments yet try to invoke it using only one. – Nkosi Feb 06 '20 at 15:07

1 Answers1

3

You have an action that takes two arguments yet try to invoke it using only one

The following example test verifies the expected behavior and that the mocking framework does in fact behave as expected.

[TestClass]
public class MyTestClass {
    [TestMethod]
    public async Task Should_Invoke_Callback() {
        //Arrange
        var someService = Substitute.For<ISomeService>();
        OneClass one = new OneClass();
        TwoClass two = new TwoClass();

        someService
            .UpdateAsync(Arg.Do<Action<OneClass, TwoClass>>(action => action(one, two)))
            .Returns(Task.CompletedTask);

        bool invoked = false;

        Action<OneClass, TwoClass> callback = (a, b) => {
            invoked = a != null && b != null;
        };

        //Act
        await someService.UpdateAsync(callback);

        //Assert - using FluentAssertions
        invoked.Should().BeTrue();
    }
}

public class TwoClass {
}

public class OneClass {
}

public interface ISomeService {
    Task UpdateAsync(Action<OneClass, TwoClass> action);
}

Reference Actions with argument matchers

Nkosi
  • 235,767
  • 35
  • 427
  • 472