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

When..Do - versatile way of configuring substitutes using delegates #825

Open
lukaszksoll opened this issue Jul 26, 2024 · 1 comment
Open

Comments

@lukaszksoll
Copy link

lukaszksoll commented Jul 26, 2024

Hi!
I'm trying to create some helper methods to make working with NSubstitute more and more convenient. There is a case, when I need to check how many or which mocks have been already created.

Let's take the following case. I have a factory that creates some type of objects.

// Implementation
public class Factory : IFactory
{
  public IComponent Create(IParameter param)
  {
    return something();
  }
}

I want to have the ability to check all of the mocks created by that factory for specified action. In order to do so, I decided to use When.. Do methods:

public static ObservableCollection<TResultObject> SetupNewSubstitute<TSubstitute, TResultObject>(this TSubstitute substitute, Action<TSubstitute> when)
  where TSubstitute : class
  where TResultObject : class
{
  var createdMocks = new ObservableCollection<TResultObject>();

  substitute
    .WhenForAnyArgs(when)
    .Do(call =>
    {
      var mock = Substitute.For<TResultObject>();
      createdMocks.Add(mock);
    });

  return createdMocks;
}

But... it does not work at all. It does not invoke Do method at all for the following case. I've already created two overloads, one for Action and another one for Func.

Test implementation:

var mockFactory = Substitute.For<IFactory>();
var createdMocks = mockFactory.SetupNewSubstitute(f => f.Create(Arg.Any<IParameter>());

// Invoking action
// createdMocks is always empty.

Previously I used to use the following pattern:

var mockList = new List<IComponent>();
mockFactory.Create(Arg.Any<IParameter>()).Returns(i =>
{
  var mockResult = Substitute.For<IComponent>();
  mockList.Add(mockResult);
  return mockResult;
})));

I've also noticed that passing any substitute/real object to var createdMocks = mockFactory.SetupNewSubstitute(f => f.Create(ANY_REAL_OBJECT_OR_SUBSTITUTE); works.

But well... it's a boilerplate for us, and we'd like to get rid of it if possible.

Are you aware of any way that it could be solved?

@dtchepak
Copy link
Member

Hi @lukaszksoll ,
Sorry for the delayed response. :(

Would you be able to post a minimal reproduction of this I can copy/paste/run in VS Code? I think just need interface IFactory and associated types (IParameter, IComponent), SetupNewSubstitute extension method, and failing test.

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

2 participants