How to moq a class with Get() and Set() methods - c#

I can't seem to moq my class that has getter and setter methods (not properties). I need to save the variable somewhere to return it later on.
Signature of my class:
public interface IMyClass
{
int Get();
void Set(int i);
}
My real implementation :
Set() => Encrypts the int and saves it in a local variable
Get() => Decrypts the int from local variable and returns int
How I want the moq to behave :
public class MyClassFake : IMyClass
{
private int _local;
public int Get()
{
return _local;
}
public void Set(int i)
{
_local = i;
}
}
What I've tried and didn't work so far :
var mockMyClass = new Mock<IMyClass>();
var number = new int();
mockMyClass.Setup(x => x.Set(It.IsAny<int>())).Callback<int>(x=> number = x);
mockMyClass.Setup(x => x.Get()).Returns(number);

You have to change Get() setup to use the overload that receives a Func<> as parameter:
var mockMyClass = new Mock<IMyClass>();
var number = 0;
mockMyClass.Setup(x => x.Set(It.IsAny<int>())).Callback<int>(x => number = x);
mockMyClass.Setup(x => x.Get()).Returns(() => number);
In your current code, you are defining Get() result as a fixed number (initial value of number)

Related

Testing whether a method was called twice with different arguments

I need to verify that a method has been invoked 2 times with specific arguments:
public void Execute()
{
Counter с = new Counter(1);
// Basically, I need to verify that DoSomething method was called twice:
// First time with an argument, which internal value is 1...
_subject.DoSomething(с);
c.Increment();
// ... and the second time - with internal value of 2
_subject.DoSomething(c);
}
Here is my verification part, with both assertions failing:
// Fails with message "Expected invocation on the mock once, but was 0 times"
mock.Verify(
m => m.DoSomething(
It.Is<Counter>(
x => x.GetValue() == 1
)
),
Times.Once
);
// Fails with message "Expected invocation on the mock once, but was 2 times"
mock.Verify(
m => m.DoSomething(
It.Is<Counter>(
x => x.GetValue() == 2
)
),
Times.Once
);
So the problem is that both invocations inside the Execute method use the same argument, which by the time of performing the assertion contains 2 as its internal value.
The question is how to make the mock to "record" the arguments somehow, so that they are evaluated correctly?
Below is the full listing:
[Test]
public void CheckSomething()
{
Mock<Subject> mock = new Mock<ISubject>();
mock.Setup(m => m.DoSomething(It.IsAny<Counter>()));
var myService = new MyService(mock.Object);
myService.Execute();
mock.Verify(m => m.DoSomething(It.Is<Counter>(x => x.GetValue() == 2)), Times.Once);
mock.Verify(m => m.DoSomething(It.Is<Counter>(x => x.GetValue() == 1)), Times.Once);
}
public interface ISubject
{
public void DoSomething(Counter с);
}
public class Subject : ISubject
{
public void DoSomething(Counter с)
{
// doesn't matter
}
}
public class MyService
{
private readonly ISubject _subject;
public MyService(ISubject subject)
{
_subject = subject;
}
public void Execute()
{
Counter с = new Counter(1);
_subject.DoSomething(с);
с.Increment();
_subject.DoSomething(с);
}
}
public class Counter
{
private int _val;
public Counter(int val)
{
_val = val;
}
public void Increment()
{
_val++;
}
public int GetValue()
{
return _val;
}
}
I really appreciate any feedback, thanks!
You can set a callback when setting up your DoSomething to track the increment of counter's value.
int counterEqual1 = 0;
int counterEqual2 = 0;
mock.Setup(m => m.DoSomething(It.IsAny<Counter>()))
.Callback<Counter>(counter =>
{
if (counter.GetValue() == 1)
counterEqual1++;
else if (counter.GetValue() == 2)
counterEqual2++;
});
Then verify those calls:
mock.Verify(m => m.DoSomething(It.IsAny<Counter>()), Times.Exactly(2));
Assert.That(counterEqual1, Is.EqualTo(1));
Assert.That(counterEqual2, Is.EqualTo(1));

Extension Method on Moq returns null

I try to test the result of some function where a call to an extension method is used. This extension method is defined on an interface. The test setup creates a mock of said interface. For this mock two setups are configured. When calling these setup function on the mocked interface implementation, everything works as intended. (see TestMockSetupSourceClassA and TestMockSetupSourceClassB) But when these calls are made in the extension method the result is null. (see TestDoClassStuff)
I've set up a test project: https://github.com/sschauss/MoqExtensionMethodTest
Extension
public static class ExtensionClass
{
public static TResult DoExtensionStuff<TResult>(this ISomeInterface someInterface, object initialObject,
params object[] objects)
{
var result = someInterface.DoInterfaceStuff<TResult>(initialObject);
return objects.Aggregate(result, (agg, cur) => someInterface.DoInterfaceStuff(cur, agg));
}
}
Implementation
public class SomeClass
{
private readonly ISomeInterface _someInterface;
public SomeClass(ISomeInterface someInterface)
{
_someInterface = someInterface;
}
public TargetClass DoClassStuff(SourceClassA sourceClassA, SourceClassB sourceClassB)
{
return _someInterface.DoExtensionStuff<TargetClass>(sourceClassA, sourceClassB);
}
}
Test
public class UnitTest
{
private readonly SomeClass _sut;
private readonly SourceClassA _sourceA;
private readonly SourceClassB _sourceB;
private readonly TargetClass _target;
private readonly Mock<ISomeInterface> _someInterfaceMock;
public UnitTest()
{
_sourceA = new SourceClassA
{
Integer = 1
};
_sourceB = new SourceClassB
{
String = "stringB"
};
_target = new TargetClass
{
Integer = 2,
String = "stringT"
};
_someInterfaceMock = new Mock<ISomeInterface>();
_someInterfaceMock.Setup(m => m.DoInterfaceStuff<TargetClass>(_sourceA)).Returns(_target);
_someInterfaceMock.Setup(m => m.DoInterfaceStuff(_sourceB, _target)).Returns(_target);
_sut = new SomeClass(_someInterfaceMock.Object);
}
[Fact]
public void TestDoClassStuff()
{
var result = _sut.DoClassStuff(_sourceA, _sourceB);
result.Should().BeEquivalentTo(_target);
}
[Fact]
public void TestMockSetupSourceClassA()
{
var result = _someInterfaceMock.Object.DoInterfaceStuff<TargetClass>(_sourceA);
result.Should().BeEquivalentTo(_target);
}
[Fact]
public void TestMockSetupSourceClassB()
{
var result = _someInterfaceMock.Object.DoInterfaceStuff(_sourceB, _target);
result.Should().BeEquivalentTo(_target);
}
}
The problem has to do with the Aggregate extension, its generic argument parameters and what you have Setup the mock to expect.
The params of the extension method DoExtensionStuff is an object array so when calling the `
T2 DoInterfaceStuff<T1, T2>(T1 parameter1, T2 parameter2)
within the Aggregate delegate you are actually passing
(TResult agg, object cur) => someInterface.DoInterfaceStuff<object,TResult>(cur, agg)
which the mock was not configured to handle.
After changing the _someInterfaceMock.Setup, in this particular case, explicitly to
_someInterfaceMock
.Setup(m => m.DoInterfaceStuff<object, TargetClass>(_sourceB, _target))
.Returns(_target);
All the tests in this scenario were able to be exercised to completion successfully.
The thing with Moq is that when a mock is not told explicitly what to expect it will return null by default for reference types.

Using Moq with HttpPostedFileBase and one other parameter

I have a method that takes 2 parameters like:
assetService(assetDto dto, HttpPostedFileBase photo)
and i can't use moq with this. How can i do that? (using 'moq')
public ResultObjectDto CreateAsset(AssetDto model, HttpPostedFileBase file)
and i want to moq this
Assert.IsTrue(_assetService.CreateAsset(new AssetDto(), postedFileBase).ResultType == ResultType.Error);
this moq is wrong, how can i do that
First you have a class you want to mock with a method with several parameters
public class foo
{
public virtual int bar(int num, string str, bool b)
{
return 1;
}
}
than to make a test you mock it
public void TestMethod1()
{
//Mock of the foo class
var t = new Mock<foo>(MockBehavior.Strict);
//Setup to return what we want 0 instead of 1
t.Setup(e => e.bar(It.IsAny<int>(), It.IsAny<string>(), It.IsAny<bool>()))
.Returns((int i, string s, bool b) => { return 0; });
//the actual object
var f = t.Object;
//the actual test
Assert.AreEqual(0, f.bar(1, "s", false));
}

Verifying an enumerable list in Moq

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))));
}

Determine if two methods have the same base definition

I've just made the unfortunate (for my app at least) discovery that two methods declared inside a generic class do not have the same base definition, demonstrated best in code:
public static class Test
{
private class Generic<T> { public void Method() { } }
public static void TestBase()
{
var x = typeof(Generic<int>).GetMethod("Method");
var y = typeof(Generic<double>).GetMethod("Method");
Debug.Assert(x.GetBaseDefinition() == y.GetBaseDefinition()); // fails
}
}
Both x and y.IsGeneric is false, so GetGenericMethodDefinition cannot be used.
The only solution I've been able to think of so far is to compare their names and that their declaring types are the same generic type, but in the presence of overloads that seems very brittle..
So.. I don't suppose there's a helpful method I've missed in the reflection library that can tell me if these two methods have been first declared in the same class? Or a workaround?
EDIT:
To clarify, I want to make a method:
public bool DeclaredInSameClass(MethodInfo a, MethodInfo b);
which returns true if both a and b are both first declared in the same class.
Ignoring generics, this is simple: a.GetBaseDefinition() == y.GetBaseDefinition(), but how to handle methods declared within generic classes?
EDIT... one last try:
private class Generic<T> {
public void Method() { }
public void Method(string param) { }
public void OtherMethod() { }
}
private class NonGeneric { public void Method() { } }
static void Main(string[] args)
{
var x = typeof(Generic<int>).GetMethod("Method", new Type[]{});
var y = typeof(Generic<double>).GetMethod("Method", new Type[]{});
var a = typeof(Generic<double>).GetMethod("OtherMethod");
var b = typeof(NonGeneric).GetMethod("Method");
var c = typeof(Generic<int>).GetMethod("Method", new Type[] { typeof(string) });
Debug.Assert(DeclaredInSameClass(x, y));
Debug.Assert(!DeclaredInSameClass(x, a));
Debug.Assert(!DeclaredInSameClass(x, b));
Debug.Assert(!DeclaredInSameClass(x, c));
Debug.Assert(!DeclaredInSameClass(a, b));
}
public static bool DeclaredInSameClass(MethodInfo a, MethodInfo b)
{
if (a.DeclaringType.IsGenericType != b.DeclaringType.IsGenericType)
{
return false;
}
else if (a.DeclaringType.IsGenericType)
{
var x = a.DeclaringType.GetGenericTypeDefinition().GetMethod(a.Name, a.GetParameters().Select(p => p.ParameterType).ToArray());
var y = b.DeclaringType.GetGenericTypeDefinition().GetMethod(b.Name, b.GetParameters().Select(p => p.ParameterType).ToArray());
return x.Equals(y);
}
return a.GetBaseDefinition().Equals(b.GetBaseDefinition());
}

Categories