forked from devlooped/moq
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid NullReferenceException with async methods
When using async methods and loose Mock Behavior, calls to Task methods give NullReferenceException, since default(Task) is null. Calls to Task.Wait() and Task<T>.Result should follow the loose behavior: do nothing and return the default value for T, respectively. Related to devlooped#64.
- Loading branch information
Alex Tercete
committed
Dec 10, 2013
1 parent
c697f94
commit a53e84e
Showing
2 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ | |
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Threading.Tasks; | ||
|
||
namespace Moq | ||
{ | ||
|
@@ -86,6 +87,11 @@ private static object GetReferenceTypeDefault(Type valueType) | |
{ | ||
return new object[0].AsQueryable(); | ||
} | ||
else if (valueType == typeof(Task)) | ||
{ | ||
// Task<T> inherits from Task, so just return Task<bool> | ||
return GetCompletedTaskWithResult(false); | ||
} | ||
else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) | ||
{ | ||
var genericListType = typeof(List<>).MakeGenericType(valueType.GetGenericArguments()[0]); | ||
|
@@ -101,6 +107,13 @@ private static object GetReferenceTypeDefault(Type valueType) | |
.MakeGenericMethod(genericType) | ||
.Invoke(null, new[] { Activator.CreateInstance(genericListType) }); | ||
} | ||
else if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(Task<>)) | ||
{ | ||
var genericType = valueType.GetGenericArguments()[0]; | ||
|
||
return GetCompletedTaskWithResult( | ||
genericType.IsValueType ? GetValueTypeDefault(genericType) : GetReferenceTypeDefault(genericType)); | ||
} | ||
|
||
return null; | ||
} | ||
|
@@ -115,5 +128,17 @@ private static object GetValueTypeDefault(Type valueType) | |
|
||
return Activator.CreateInstance(valueType); | ||
} | ||
|
||
private static Task GetCompletedTaskWithResult<TResult>(TResult value) | ||
{ | ||
var type = value.GetType(); | ||
var tcs = Activator.CreateInstance(typeof (TaskCompletionSource<>).MakeGenericType(type)); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
alextercete
Owner
|
||
|
||
var setResultMethod = tcs.GetType().GetMethod("SetResult"); | ||
var taskProperty = tcs.GetType().GetProperty("Task"); | ||
|
||
setResultMethod.Invoke(tcs, new object[] {value}); | ||
return (Task) taskProperty.GetValue(tcs, null); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Why not use reflection to call the static Task.FromResult(T result) method? Or is this targeting older frameworks? (I believe this method was added in .NET 4.5
http://msdn.microsoft.com/en-us/library/hh194922(v=vs.110).aspx