I have a class that receives an ICacheManager via injection:
public ClientIdToClientNameResolver(IDataManager<Client> clientManager, ICacheManager cacheManager, ILogUtils logUtils)
{
this.clientManager = clientManager;
this.cacheManager = cacheManager;
this.logUtils = logUtils;
}
There is a line of code that then executes the Get method on it:
var client = cacheManager
.Get(CacheKeys.Clients, () => clientManager.Get())
.FirstOrDefault(x => x.Id == clientId);
The signature for that method is:
TResult Get<TResult>(string key, Func<TResult> defaultValue = null)
That specific execution of Get has a TResult of List<Client> and so I'm mocking it up like this:
var cacheManagerMock = new Mock<ICacheManager>();
cacheManagerMock.Setup(m => m.Get(It.IsAny<string>(), It.IsAny<Func<List<Client>>>()))
.Returns(new List<Client>());
However, when executing the test, the call to:
var client = cacheManager
.Get(CacheKeys.Clients, () => clientManager.Get())
is returning null. I know that because in a previous iteration I broke that statement out on its own. What did I do wrong with the Mock?
The following [mcve] was used to try and reproduce the issue based on the original example provided.
[TestClass]
public class UnitTest4 {
[TestMethod]
public void TestMethod1() {
//Arrange
var clients = new List<Client>(){
new Client { Id = 1 }
};
var cacheManagerMock = new Mock<ICacheManager>();
cacheManagerMock
.Setup(m => m.Get(It.IsAny<string>(), It.IsAny<Func<List<Client>>>()))
.Returns(clients);
var clientId = 1;
var clientManager = Mock.Of<IDataManager<Client>>();
var cacheManager = cacheManagerMock.Object;
//Act
var client = cacheManager
.Get(CacheKeys.Clients, () => clientManager.Get())
.FirstOrDefault(x => x.Id == clientId);
//Assert
Assert.IsNotNull(client);
}
public class Client { public int Id { get; set; } }
public interface ICacheManager {
TResult Get<TResult>(string key, Func<TResult> defaultValue = null);
}
public interface IDataManager<T> {
List<T> Get();
}
public class CacheKeys {
public const string Clients = "FakeKey";
}
}
However the test passes as expected.
Related
Hi I am trying to mock the following thing:
var result = _scope.Execute<FooService, IList<FooEntity>>(x => x.GetFooEntities(fooModel));
This is how I try to mock it:
_mockedScope
.Setup(x => x.Execute<FooService, IList<FooEntity>>(f => f.GetFooEntities(It.IsAny<FooModel>())))
.Returns(new List<FooEntity>)
But when I run the test it throws me an exception
Unsupported expression: s => s.GetFooEntities(IsAny())
Any suggestions how can I mock it?
Here is an example what i want to moq
public class Test
{
private readonly IScope _scope;
public Test(IScope scope)
{
_scope = scope;
}
public void Foo()
{
var foo = new FooEntity();
Result<IList<Foo>> result =
_scope.Execute<FooService, IList<Foo>>(
"f",
s => s.GetFoo(foo));
}
}
public class Foo
{
}
public class FooEntity
{
}
public class FooService
{
public List<Foo> GetFoo(FooEntity f);
}
public interface IScope
{
Result<TResult> Execute<T1, TResult>(string temp, Func<T1, TResult> function);
}
public class Result<T>
{
private Result(T value, Exception exception)
{
Value = value;
Error = exception;
}
public Exception Error { get; }
public T Value { get; }
public bool HasError => Error != null;
public static Result<T> Fail(Exception exception) => new Result<T>(default(T), exception);
public static Result<T> Success(T value) => new Result<T>(value, null);
}
While expressions are used by moq to setup mocks, you are trying to mock an expression. This tends to be very difficult with Moq but there are workarounds via matched arguments.
Assuming Scope.Execute method is defined like
public interface IScope {
Result<TResult> Execute<T, TResult>(string temp, Func<T, TResult> function);
}
Use It.IsAny to allow for flexibility when setting up a mock that relies on an expression argument.
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
The It.IsAny<Func<FooService, IList<Foo>>>() will cover s => s.GetFoo(foo) in the invoked code.
Given
public class Test {
private readonly IScope _scope;
public Test(IScope scope) {
_scope = scope;
}
public IList<Foo> Foo() {
var foo = new FooEntity();
Result<IList<Foo>> result = _scope.Execute<FooService, IList<Foo>>("f", s => s.GetFoo(foo));
var value = result.Value;
return value;
}
}
The following complete example was used to demonstrate what was explained above
[TestClass]
public class ExpressionMock {
[TestMethod]
public void TestFoo() {
//Arrange
var _mockedScope = new Mock<IScope>();
_mockedScope
.Setup(x => x.Execute<FooService, IList<Foo>>(It.IsAny<string>(), It.IsAny<Func<FooService, IList<Foo>>>()))
.Returns(Result<IList<Foo>>.Success(new List<Foo>()));
var subject = new Test(_mockedScope.Object);
//Act
var actual = subject.Foo();
//Assert
actual.Should().NotBeNull();
}
}
Reference Moq Quickstart to get a better understanding of how to use the framework
I'm working with some legacy code which I require to write some unit tests for. There is data access method with the following signature.
Task ExecuteReaderAsync(string procedureName, Parameters procedureParameters,
params Action<System.Data.IDataReader>[] actions);
which there is an implementation in the class i'm testing similar to this
private async Task<CustomObject> GetCustomObject(int id)
{
CustomObject obj = null;
await db.ExecuteReaderAsync("nameOfProcedure", some parameters,
dr =>
{
obj = new CustomObject()
{
Prop1 = dr["Col1"],
Prop2 = dr["Col2"]
}
}
return obj;
}
What I'm struggling with is being able to control the values returned by GetCustomObject. If ExecuteReaderAsync actually returned something I could have a set up like this.
mockDataAccess.Setup(x => x.ExecuteReaderAsync("nameOfProcedure", It.IsAny<Parameters>()))
.Returns(Task.FromResult(new CustomeObject() { prop1 = "abc", prop2 = "def"};));
But the logic for specifying the values is an Action<IDataReader> which I don't control. I'm wondering if there are any tricks I could employ to do what I want,
i.e. control the value of the object returned by GetCustomObject.
Take a look at the following example
[TestClass]
public class LegacyCodeTest {
[TestMethod]
public async Task TestExecuteReaderAsync() {
//Arrange
var mapping = new Dictionary<string, string> {
{ "Col1", "abc" },
{ "Col2", "def" }
};
var mockDataReader = new Mock<IDataReader>();
mockDataReader
.Setup(m => m[It.IsAny<string>()])
.Returns<string>(col => mapping[col])
.Verifiable();
var mockDataAccess = new Mock<IDataAccess>();
mockDataAccess
.Setup(m => m.ExecuteReaderAsync("nameOfProcedure", It.IsAny<Parameters>(), It.IsAny<Action<System.Data.IDataReader>[]>()))
.Returns(Task.FromResult<object>(null))
.Callback((string s, Parameters p, Action<System.Data.IDataReader>[] a) => {
if (a != null && a.Length > 0) {
a.ToList().ForEach(callback => callback(mockDataReader.Object));
}
})
.Verifiable();
var sut = new SUT(mockDataAccess.Object);
//Act
var actual = await sut.MUT(2);
//Assert
mockDataAccess.Verify();
mockDataReader.Verify(m => m["Col1"]);
mockDataReader.Verify(m => m["Col2"]);
actual.Should()
.NotBeNull()
.And
.Match<CustomObject>(c => c.Prop1 == mapping["Col1"] && c.Prop2 == mapping["Col2"]);
}
public interface IDataAccess {
Task ExecuteReaderAsync(string procedureName, Parameters procedureParameters, params Action<System.Data.IDataReader>[] actions);
}
public class Parameters { }
public class CustomObject {
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class SUT {
IDataAccess db;
public SUT(IDataAccess dataAccess) {
this.db = dataAccess;
}
public async Task<CustomObject> MUT(int id) {
var result = await GetCustomObject(id);
return result;
}
private async Task<CustomObject> GetCustomObject(int id) {
CustomObject obj = null;
await db.ExecuteReaderAsync("nameOfProcedure", null,
dr => {
obj = new CustomObject() {
Prop1 = dr["Col1"],
Prop2 = dr["Col2"]
};
});
return obj;
}
}
}
Since you don't have control of the Action<IDataReader>, in this case the most that can be done is to make sure that the action does not fail. So that would mean passing an a mock reader that performs as expected for the action.
var mapping = new Dictionary<string, string> {
{ "Col1", "abc" },
{ "Col2", "def" }
};
var mockDataReader = new Mock<IDataReader>();
mockDataReader
.Setup(m => m[It.IsAny<string>()])
.Returns<string>(col => mapping[col])
.Verifiable();
by using the call back to get access to the passed in parameters
.Callback((string s, Parameters p, Action<System.Data.IDataReader>[] a) => {
if (a != null && a.Length > 0) {
a.ToList().ForEach(callback => callback(mockDataReader.Object));
}
})
the mocked reader can be passed to the actions called within the method under test.
This answer is tailored to the provided example in th OP so some modification may need to be made for it to apply to your specific scenario. This should be enough to get you going for situations like this.
I'm trying to mock this method
Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc)
like this
iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, object>>())).ReturnsAsync(new { isPair = false });
The method to test doing the call passing an anonymous type to the generic parameter like this
instance.GetResultAsync(u => new {isPair = u == "something" }) //dont look at the function return because as generic could have diferent implementations in many case
Moq never matches my GetResultAsync method with the parameters sent.
I'm using Moq 4
The anonymous type is going to cause you problems. You need a concrete type for this to work.
The following example worked when I changed
instance.GetResultAsync(u => new {isPair = u == "something" })
to
instance.GetResultAsync(u => (object) new {isPair = u == "something" })
Moq is unable to match the anonymous type and that is why you get null when called.
[TestClass]
public class MoqUnitTest {
[TestMethod]
public async Task Moq_Function_With_Anonymous_Type() {
//Arrange
var expected = new { isPair = false };
var iMock = new Mock<IService>();
iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, object>>()))
.ReturnsAsync(expected);
var consumer = new Consumer(iMock.Object);
//Act
var actual = await consumer.Act();
//Assert
Assert.AreEqual(expected, actual);
}
public interface IService {
Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc);
}
public class Consumer {
private IService instance;
public Consumer(IService service) {
this.instance = service;
}
public async Task<object> Act() {
var result = await instance.GetResultAsync(u => (object)new { isPair = u == "something" });
return result;
}
}
}
if the code calling the GetResultAsync is dependent on using the anonymous type then what you are trying to do with your test wont work with your current setup. You would probably need to provide a concrete type to the method.
[TestClass]
public class MoqUnitTest {
[TestMethod]
public async Task Moq_Function_With_Concrete_Type() {
//Arrange
var expected = new ConcreteType { isPair = false };
var iMock = new Mock<IService>();
iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, ConcreteType>>()))
.ReturnsAsync(expected);
var sut = new SystemUnderTest(iMock.Object);
//Act
var actual = await sut.MethodUnderTest();
//Assert
Assert.AreEqual(expected, actual);
}
class ConcreteType {
public bool isPair { get; set; }
}
public interface IService {
Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc);
}
public class SystemUnderTest {
private IService instance;
public SystemUnderTest(IService service) {
this.instance = service;
}
public async Task<object> MethodUnderTest() {
var result = await instance.GetResultAsync(u => new ConcreteType { isPair = u == "something" });
return result;
}
}
}
Edit2: removed a load of gubbins + bounty.
I have deconstructed an expression for a message bus in the hope of reconstructing it and invoking it in a slightly different manner. The serialization and deserialization is successful and I am able to create instances of most of what I need.
//Deconstruct
Expression<Func<T, Task>> expression
proxy => proxy.serviceMethod(arg);
I need to create the syntax below. T is an interface to a WCF service. This expression will be passed to a service invoker where it's internal ChannelFactory will pass it into this method.
//Reconstruct this as expression so I can pass it as a parameter
var myAction = new Action<T>(proxy => {
proxy.serviceMethod((SomeType)SomeParameter));
});
// to pass to this method
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { myAction });
What I have:
//I think i'm nearly there I can create the inner call and assign
//the correct parameter, but I can't seem to figure out how to wrap it in an
// new Action<serviceT> { my other expressions... }
// Types
var serviceT = Type.GetType(workOutMessage.interfaceType);
var actionT = typeof(Action<>).MakeGenericType(serviceT);
var envelopeT = Type.GetType(workOutMessage.methodArgTypes[0]);
// ServiceInvoker<T> Instantiation - Works
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, client.Id, "password", clientCert, serviceCert);
// Expression Type Params
var serviceTParam = Expression.Parameter(serviceT, "proxy");
var envelopeParam = Expression.Parameter(envelopeT, "envelope");
var envAssign = Expression.Assign(envelopeParam, Expression.Constant(workOutMessage.methodArgs[0]));
var methodCall = Expression.Call(serviceTParam, serviceT.GetMethod(workOutMessage.methodName), envelopeParam);
// var lambda = ...
// make new Action<serviceT> myAction = { proxy => proxy.someMethod(someParameter); };
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { lambda.Compile() });
Edit: The Service Invoker Method I pass this into to, to try and give the problem better context.
public void InvokeService(Action<T> handler)
{
T proxy = channelFactory.CreateChannel();
((IClientChannel)proxy).Faulted += ChannelFaulted;
ICommunicationObject obj2 = (ICommunicationObject)proxy;
try
{
using (new OperationContextScope((IContextChannel)proxy))
{
handler.Invoke(proxy);
}
}
finally
{
try
{
if (obj2.State != CommunicationState.Faulted)
{
obj2.Close();
}
}
catch
{
obj2.Abort();
}
}
}
Here is a full piece of code, in which I assume you only need a Func, not an Action.
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace HelloWorld
{
public class Service1
{
public Task ServiceMethod(string something)
{
return Task.Factory.StartNew(() => Console.WriteLine(something));
}
}
public class HubServiceInvoker<T> where T : new()
{
T t;
public HubServiceInvoker(string id, string password)
{
t = new T();
}
public void InvokeService(Func<T, Task> serviceInvoker)
{
Task task = serviceInvoker(t);
}
public static Func<T, Task> CompileInvoker(Expression expression, ParameterExpression serviceTParam)
{
Expression<Func<T, Task>> lambda = Expression.Lambda<Func<T, Task>>(expression, serviceTParam);
return lambda.Compile();
}
}
public class WorkOutMessage
{
public string interfaceType { get; set; }
public string[] methodArgTypes { get; set; }
public object[] methodArgs { get; set; }
public string methodName { get; set; }
}
static class Program
{
static void Main(string[] args)
{
WorkOutMessage workOutMessage = new WorkOutMessage()
{
interfaceType = "HelloWorld.Service1",
methodArgTypes = new string[] { "System.String" },
methodArgs = new object[] { "yeah it works!" },
methodName = "ServiceMethod"
};
InvokeService(workOutMessage);
Console.Read();
}
static void InvokeService(WorkOutMessage workOutMessage)
{
// Types
var serviceT = Type.GetType(workOutMessage.interfaceType);
// ServiceInvoker<T> Instantiation - Works
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceCompileInvokerTMethod = serviceInvokerT.GetMethod("CompileInvoker");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, "id", "password");
// Expression Type Params
var serviceTParam = Expression.Parameter(serviceT, "proxy");
var methodCall = Expression.Call(serviceTParam, serviceT.GetMethod(workOutMessage.methodName), Expression.Constant(workOutMessage.methodArgs[0]));
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] {
serviceCompileInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { methodCall, serviceTParam })
});
}
}
}
It was a little bit hard to understand what exactly is going on.
Perhaps, this will help you a little bit further:
// Helper.cs
public static Action<TType> Wrap<TType>(Delegate test)
{
return ret => test.DynamicInvoke();
}
var meth = typeof(Helper).GetMethod("Wrap");
var gmeth = meth.MakeGenericMethod(new[] { serviceT });
var genericAction = gmeth.Invoke(null, new object[] {
Expression.Lambda(methodCall).Compile(); });
Thanks to the hints from #Romain Hautefeuille, the key was to use my generic ServiceInvoker class to help me create the action that I needed without the need of using Expressions (woohoo).
// Execute Interface method from interface, methodName and methodArgs from message queue
var serviceT = Type.GetType(workOutMessage.interfaceType);
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceInvokerCompileTMethod = serviceInvokerT.GetMethod("CompileServiceMethod");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, client.Id,
"password", clientCert, serviceCert);
// Works! and a lot simpler
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] {
workOutMessage.correlationId,
serviceInvokerCompileTMethod.Invoke(serviceInvokerTInstance, new object[] {
workOutMessage.methodName,
workOutMessage.methodArgs })
});
And Finally the new method in the ServiceInvoker class (I wanted to avoid reflection in this class - for no particular reason - but it doesn't affect calling it normally).
public Action<T> CompileServiceMethod(string methodName, object[] methodArguments)
{
return new Action<T>(proxy =>
{
typeof(T).GetMethod(methodName).Invoke(proxy, methodArguments);
});
}
I'm trying to write a unit test for a method which looks like this:
public int Save(IEnumerable<int> addedIds, IEnumerable<int> removedIds)
{
var existingIds = repository.Get();
IEnumerable<int> ids = existingIds.Except(removedIds).Union(addedIds));
return repository.Create(ids);
}
The test in Moq looks like this:
repository.Setup(r => r.Get()).Returns(CreateList());
service.Save(addedIds, removedIds);
repository.Verify(r => r.Create(It.Is<IEnumerable<int>>(l => VerifyList(l))));
This fails, with this error, and VerifyList() is never called:
Expected invocation on the mock at least once, but was never
performed:
r => r.Create(It.Is<IEnumerable'1>(list => VerifyList(list)))
Performed invocations:
IRepo.Create(System.Linq.Enumerable+<UnionIterator>d__88'1[System.Int32])
As the invoked type is not IEnumerable<int> but is in fact System.Linq.Enumerable+<UnionIterator>d__88'1[System.Int32]), the test fails. (Stepping through the test, everything is happening correctly and the results are as expected)
If I call ids.ToList() in the method under test, these are the results:
Expected invocation on the mock at least once, but was never performed:
r => r.Create(It.Is<List'1>(l => VerifyList(l)))
Performed invocations:
IRepo.Create(System.Collections.Generic.List'1[System.Int32])
Is there any way round this? Or am I doing something wrong?
Edit: it turns out I had a mistake in my VerifyList method so it was returning false, but Moq wasn't giving me that information. The type difference is a red herring..
This seems to work. Made some assumptions though. Guess the VerifyList method could be better. =)
[Test]
public void Test()
{
// SETUP
Mock<IRepository> repository = new Mock<IRepository>();
Service service = new Service(repository.Object);
repository.Setup(r => r.Get()).Returns(CreateList());
IEnumerable<int> addedIds = new[]{1,2};
IEnumerable<int> removedIds = new[]{3,4};
service.Save(addedIds, removedIds);
repository.Verify(r => r.Create(It.Is<IEnumerable<int>>(l => VerifyList(l))));
}
private static bool VerifyList(IEnumerable<int> enumerable)
{
return enumerable.Contains(1) && enumerable.Contains(2) && enumerable.Contains(5);
}
private IEnumerable<int> CreateList()
{
return new[] { 3, 4, 5 };
}
public interface IRepository
{
IEnumerable<int> Get();
int Create(IEnumerable<int> id);
}
public class Service
{
public Service(IRepository repository)
{
this.repository = repository;
}
private IRepository repository;
public int Save(IEnumerable<int> addedIds, IEnumerable<int> removedIds)
{
var existingIds = repository.Get();
IEnumerable<int> ids = existingIds.Except(removedIds).Union(addedIds);
return repository.Create(ids);
}
You can do:
var another = new List<int> { 1 , 2, 3 };
repository.Verify(r => r.Create(It.Is<IEnumerable<int>>(l => l.SequenceEqual(another)));
Something quick and dirty -
public interface IBlah
{
void Sum(IEnumerable<int> baz);
}
class Blah : IBlah
{
public void Sum(IEnumerable<int> baz)
{
return;
}
}
public class Baz
{
private readonly IBlah blah;
public Baz(IBlah blah)
{
this.blah = blah;
}
public void Sum(IEnumerable<int> baz)
{
blah.Sum(baz);
}
}
And Test it like -
[Test]
public void foo()
{
var mock = new Mock<IBlah>();
var enumerable = Enumerable.Range(1, 10);
var baz = new Baz(mock.Object);
baz.Sum(enumerable.Where(x => x%2 == 0));
mock.Verify(p => p.Sum(It.Is<IEnumerable<int>>(z => z.All(x => x%2==0))));
}