-
Notifications
You must be signed in to change notification settings - Fork 265
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
Customize SubstituteFactory. #751
Comments
I am not aware of any inbuild NSubstitute feature for this. Normally I use NSubstitute in conjunction with AutoFixture. So basically instead of
you have to write
To make it work like you desire, just create your fixture e.g. like this:
|
Hi @kekchpek , |
@Ergamon thank you for noticing such a good tool for testing as AutoFixture! It almost the thing I had been looking for. But I also need make substitutes for my generic promises, and I didn't find a way to do it with AutoFixture quickly. ...
// I run this one time before all tests.
var customizedContainer = NSubstituteDefaultFactory.DefaultContainer.Customize();
customizedContainer.Decorate<IAutoValueProvidersFactory>((factory, _) => new PromiseValueProviderFactory(factory));
SubstitutionContext.Current = customizedContainer.Resolve<ISubstitutionContext>();
...
public class PromiseValueProviderFactory : IAutoValueProvidersFactory
{
private readonly IAutoValueProvidersFactory _original;
private class PromiseValueProvider : IAutoValueProvider
{
private readonly Dictionary<Type, object> _completedPromises = new();
public bool CanProvideValueFor(Type type)
{
return type == typeof(IPromise) || type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IPromise<>);
}
public object GetValue(Type type)
{
if (type == typeof(IPromise))
return PromiseTool.GetSuccessful();
if (type.GetGenericTypeDefinition() == typeof(IPromise<>))
return GetSuccessful(type.GenericTypeArguments.Single());
throw new InvalidOperationException($"Can not create promise for type {type.Name}");
}
private object GetSuccessful(Type t)
{
if (_completedPromises.TryGetValue(t, out var p))
return p;
var promiseTool = typeof(PromiseTool);
var getMethod = promiseTool.GetMethods(BindingFlags.Public | BindingFlags.Static)
.Single(x => x.Name == nameof(PromiseTool.GetSuccessful) && x.IsGenericMethod);
var completedPromise =
Expression.Lambda(Expression.Call(
getMethod.MakeGenericMethod(t),
Expression.Default(t))).Compile().DynamicInvoke();
_completedPromises.Add(t, completedPromise);
return completedPromise;
}
}
public PromiseValueProviderFactory(IAutoValueProvidersFactory original)
{
_original = original;
}
public IReadOnlyCollection<IAutoValueProvider> CreateProviders(ISubstituteFactory substituteFactory)
{
return new [] {new PromiseValueProvider()}.Concat(_original.CreateProviders(substituteFactory)).ToArray();
}
} |
I ran onto a problem.
In my program I work a lot with async code and I have my own types(including interfaces) to work with
async
/await
keywords. I also use standard tasks library. So the interface of an object with async methods could look like this:NSubstitute mock every
Task
with a completed task by default. I'd like to make pretty same thing for myIPromise
.I surfed the internet and found couple of topics: this and other and one more, but didnt' found suitable solution there.
It will be cool if I could configure
SubstituteFactory
with some method like this:Or maybe this method should be a part of a context.
Or event provide an ability to rewrite SubstituteFactory with some proxy. It could solve other problems, when you want specific behaviour for mocks creation.
All of this are just my rough thoughts about the implementation. It could be completely different, but I hope my problem is clear. If NSubstitute already has solution for such kind of problems, please tell me.
The text was updated successfully, but these errors were encountered: