Default mock for specific type in NSubstitute

63 Views Asked by At

Is there a way to specify a return object for every method and property of specific type?

For example I want all method, that returns string, return "TestString" instead of null.

Usually, I have to write something like this:

        public interface ISomeInterface
        {
            string GetValue();
            
        }

        public void Test()
        {
            var mock1 = Substitute.For<ISomeInterface>();
            mock1.GetValue().Returns("TestString");
            var mock2 = Substitute.For<ISomeInterface>();
            mock2.GetValue().Returns("TestString");
            
            // ... test something
        }

But is there a way to specify that all created ISomeInterface substutes will return "TestString" for GetValue() method?

PS. There is an issue at NSubstitute github, where I've asked the same question with more specific details. https://github.com/nsubstitute/NSubstitute/issues/751

1

There are 1 best solutions below

0
Nikolai On BEST ANSWER

The answer is written here - https://github.com/nsubstitute/NSubstitute/issues/751.

Long story short, you have to implement IAutoValueProvider and IAutoValueProviderFactory for your type. For this specific case it could look like this:

    
// run this one time before all of your tests
...
var customizedContainer = NSubstituteDefaultFactory.DefaultContainer.Customize();
customizedContainer.Decorate<IAutoValueProvidersFactory>((factory, _) => new StringValueProviderFactory(factory));
SubstitutionContext.Current = customizedContainer.Resolve<ISubstitutionContext>();
...    

public class StringValueProviderFactory : IAutoValueProvidersFactory
{
    private readonly IAutoValueProvidersFactory _original;

    private class StringValueProvider : IAutoValueProvider
    {
        public bool CanProvideValueFor(Type type)
        {
            return type == typeof(string);
        }

        public object GetValue(Type type)
        {
            if (type == typeof(string))
                return "TestString";
            throw new InvalidOperationException($"Can not create string for type {type.Name}");
        }
    }

    public StringValueProviderFactory(IAutoValueProvidersFactory original)
    {
        _original = original;
    }
    
    public IReadOnlyCollection<IAutoValueProvider> CreateProviders(ISubstituteFactory substituteFactory)
    {
        return new [] {new StringValueProvider()}.Concat(_original.CreateProviders(substituteFactory)).ToArray();
    }
}