vanderkleij / Smocks

Smocks is a library for mocking the normally unmockable. It can mock static and non-virtual methods and properties, amongst others.
MIT License
114 stars 26 forks source link

NullReferenceException #18

Open msallin opened 8 years ago

msallin commented 8 years ago

Hi

I try to use Smock like this

Smock.Run(context =>
{
    context.Setup(() => DateTime.Now).Returns(DateTime.Now.AddDays(1));
    context.Setup(() => DateTime.UtcNow).Returns(DateTime.UtcNow.AddDays(1));
    Task<IList<TEntity>> myTask = Add();
    myTask.RunSynchronously();
});

Then I get a null reference:

Smocks.AppDomains.AppDomainContext.InvokeSerializableLambda[T](SerializableLambda`1 serializableFunc, Object target, Object[] arguments)
   at Smocks.AppDomains.AppDomainContext.Invoke[T](Action`1 action, T parameter)
   at Smocks.Smock.RunAction(Action`1 action, Configuration configuration)
   at Smocks.Smock.Run(Configuration configuration, Action`1 action)
   at Smocks.Smock.Run(Action`1 action)

Is this a bug or a limitation?

EDIT: For the same code, when running a different test I get another error

System.TypeLoadException : Could not load type 'TEntity' from assembly 'xy.xy.Shared.TesterCore, Version=0.0.0.1, Culture=neutral, PublicKeyToken=46adc5b7b509fbee'.

   at System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at Smocks.IL.Resolvers.AssemblyTypeContainer.GetType(String name)
   at Smocks.IL.Resolvers.TypeResolver.Resolve(TypeReference type, GenericBindingContext bindingContext)
   at Smocks.IL.Resolvers.TypeResolver.<>c__DisplayClass3_0.<Resolve>b__1(TypeReference argument)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Smocks.IL.Resolvers.TypeResolver.Resolve(TypeReference type, GenericBindingContext bindingContext)
   at Smocks.IL.Resolvers.TypeResolver.<>c__DisplayClass3_0.<Resolve>b__1(TypeReference argument)
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
   at Smocks.IL.Resolvers.TypeResolver.Resolve(TypeReference type, GenericBindingContext bindingContext)
   at Smocks.IL.Resolvers.TypeResolver.Resolve(TypeReference type)
   at Smocks.IL.DynamicMethodCompiler.<>c__DisplayClass5_0.<AddVariables>b__1(VariableReference variable)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector)
   at Smocks.IL.DynamicMethodCompiler.AddVariables(IILGenerator generator, IEnumerable`1 variables)
   at Smocks.IL.DynamicMethodCompiler.Compile[T](TypeReference[] parameters, IEnumerable`1 instructions, IEnumerable`1 variables)
   at Smocks.IL.ExpressionDecompiler.Decompile(MethodBody body, Instruction instruction, Object target)
   at Smocks.IL.SetupExtractor.<GetSetupsFromInstructions>d__10.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at Smocks.Smock.CreateAssemblyRewriter(Delegate delegate, Configuration configuration)
   at Smocks.Smock.RunAction(Action`1 action, Configuration configuration)
   at Smocks.Smock.Run(Configuration configuration, Action`1 action)
   at Smocks.Smock.Run(Action`1 action)
vanderkleij commented 8 years ago

Hi, thanks for reporting this. From the looks of it, TEntity is most likely a generic type parameter, and not an actual type. Can you confirm this? Can you expand the code example to a minimal, complete example that illustrates how/where TEntity is defined?

msallin commented 8 years ago

I'm calling a method which looks like that.

protected virtual async Task<IList<TEntity>> AddEntities(int amount, Action<TEntity> action)
{
    IList<TEntity> entityList = new List<TEntity>();
    for (int i = 0; i < amount; i++)
    {
        TEntity entity = CreateEntity();
        action(entity);
        var result = await Repository.InsertAsync(entity);
        result.EnsureIsValid();
        entityList.Add(entity);
    }

    return entityList;
}

Where the TEntity is RepositoryFixture<TEntity, TFilter, TRepository> : Fixture where TEntity : IEntity where TFilter : IFilter where TRepository : IRepository<TEntity, TFilter>

vanderkleij commented 8 years ago

This appears to be a bug. I will investigate and fix it in the near future. Thanks for reporting again!

msallin commented 8 years ago

Hi

To make it easier to reproduce I created a new project which contains the structure we use. You can download it here: https://onedrive.live.com/redir?resid=C8E1BE3E79378699!631447&authkey=!AMlmgIqoGQ70pwI&ithint=file%2czip

Here I use Moq to abstract the repository. In the real tests there is a repository which abstracts the Entity Framework to access the database. I'm not sure if this is relevant for this bug.

However, I'm also not able to get this project run. There is another exception which is thrown. May this is depended to the this issue.

Please let me know when you need additional help.

Greetings

ujeshmaurya commented 4 years ago

Hello @vanderkleij This bug is resolved or not? As I am facing the same issue of NullReferenceException while using Smocks. I tried to run the examples which you gave in the Readme file, they are giving the same exceptions.

iwl commented 2 years ago

Hello @vanderkleij @ujeshmaurya This bug is resolved or not? As I am facing the same issue

I am also today, trying to smock DateTime.Now / Today Probably the most common use case and seems to be a common problem below Enterprise version...