I have this class:
class MyClass
{
private ISomeInterface blabla;
public MyClass() : this(new SomeInterfaceImplementation()) {}
internal MyClass(ISomeInterface blabla)
{
this.blabla = blabla;
}
public void SomeMethod(string id, int value1, int value2)
{
this.blabla.DoSomethingWith(id, new ValueClass(value1, value2))
}
}
I also have this test:
[TestFixture]
public class MyClassTest
{
private const string ID = "id";
private const int VALUE1 = 1;
private const int VALUE2 = 2;
private ValueClass valueClass;
private Mock<ISomeInterface> mockInterface;
private MyClass myClass;
[SetUp]
public void SetUp()
{
this.valueClass = new ValueClass(VALUE1, VALUE2);
this.mockInterface = new Mock<ISomeInterface>();
this.myClass = new MyClass(this.mockInterface.Object);
}
[Test]
public void GIVEN_AnID_AND_AValue1_AND_AValue2_WHEN_DoingSomeMethod_THEN_TheSomeInterfaceShouldDoSomething()
{
this.myClass.SomeMethod(ID, VALUE1, VALUE2);
this.mockInterface.Verify(m => m.DoSomethingWith(ID, this.valueClass), Times.Once()); //<- Test fails here!
}
}
I don't know why but I can't get this test to pass. NCrunch is giving me the following error message:
Moq.MockException : Expected invocation on the mock once, but was 0 times: m => m.DoSomethingWith("ID", .valueClass) No setups configured.
Performed invocations:
ISomeInterface.DoSomethingWith("ID", MyNamespace.ValueClass) at Moq.Mock.ThrowVerifyException(MethodCall expected, IEnumerable
1 setups, IEnumerable
1 actualCalls, Expression expression, Times times, Int32 callCount) at Moq.Mock.VerifyCalls(Interceptor targetInterceptor, MethodCall expected, Expression expression, Times times) at Moq.Mock.Verify[T](Mock1 mock, Expression
1 expression, Times times, String failMessage) at Moq.Mock1.Verify(Expression
1 expression, Times times) at Tests.MyClassTest.GIVEN_AnID_AND_AValue1_AND_AValue2_WHEN_DoingSomeMethod_THEN_TheSomeInterfaceShouldDoSomething() in C:\MySourceCode\File and line number here.
As you can see, it seems like Moq is "not seeing" my invocation, probably because of the new ValueClass(value1, value2)
how can I make this test pass or how can I change my design so it is easier to test? Where should I put the new ValueClass(value1, value2)
?
EDIT:
Is this a question I should ask on Software Engineering instead of StackOverflow? Is this out of scope?
Your problem is not matching argument in method call: this.valueClass
by default is not equal to new ValueClass(value1, value2)
because it will be two different instances of ValueClass
. And by default two instances will be compared by references, which are different. You can:
Equals
and GetHashCode
methods in ValueClass
to change the way how two instances compared. I.e. compare by values instead of comparing by references.It.Any<ValueClass>()
. It's good if you don't care about specific values of ValueClass
and just want to check method was called. Not always best optionValueClass
manually: It.Is<ValueClass>(vc => vc.Value1 == VALUE1 && vc.Value2 == VALUE2)
. Sometimes it's also good. E.g. if you cannot override Equals
. But it makes tests much less readable.