Reputation: 28560
I have a setup similar to below:
[TestMethod]
public void NoIntegers()
{
Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);
mockBar
.SetupGet(x => x.Integers)
.Returns(mockIntegers.Object);
mockIntegers
.Setup(x => x.Any())
.Returns(false);
Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
}
public interface IBar
{
IEnumerable<int> Integers { get; }
}
public class Foo
{
private IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public bool AreThereIntegers()
{
return _bar.Integers.Any();
}
}
}
When it runs it fails to initialise the mock
Test method NoIntegers threw exception: System.NotSupportedException: Expression references a method that does not belong to the mocked object: x => x.Any<Int32>()
I have tries adding It.IsAny()
in a few forms:
mockIntegers
.Setup(x => x.Any(It.IsAny<IEnumerable<int>>(), It.IsAny<Func<int, bool>>()))
.Returns(false);
// No method with this signiture
mockIntegers
.Setup(x => x.Any(It.IsAny<Func<int, bool>>()))
.Returns(false);
// Throws: Test method NoIntegers threw exception:
// System.NotSupportedException:
// Expression references a method that does not belong to the mocked object:
// x => x.Any<Int32>(It.IsAny<Func`2>())
What do I need to mock in order for this to run?
Upvotes: 6
Views: 4858
Reputation: 38508
You need to mock Integers
property only. There is no need to mock Any()
(you can't do it anyway because it's an extension method) because it is a part of SUT. Here's how you should do it for two cases:
[TestMethod]
public void NoIntegers()
{
Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
mockBar.SetupGet(x => x.Integers)
.Returns(new List<int>());
Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
}
[TestMethod]
public void HasIntegers()
{
Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
mockBar.SetupGet(x => x.Integers)
.Returns(new List<int>{ 3, 5, 6});
Assert.IsTrue(new Foo(mockBar.Object).AreThereIntegers());
}
Upvotes: 2
Reputation: 28560
Fixed!
Not pretty, but this is the mocking that's needed:
[TestMethod]
public void NoIntegers()
{
Mock<IBar> mockBar = new Mock<IBar>(MockBehavior.Strict);
Mock<IEnumerable<int>> mockIntegers = new Mock<IEnumerable<int>>(MockBehavior.Strict);
Mock<IEnumerator<int>> mockEnumerator = new Mock<IEnumerator<int>>(MockBehavior.Strict);
mockBar
.SetupGet(x => x.Integers)
.Returns(mockIntegers.Object);
mockIntegers
.Setup(x => x.GetEnumerator())
.Returns(mockEnumerator.Object);
mockEnumerator.Setup(x => x.MoveNext()).Returns(false);
mockEnumerator.Setup(x => x.Dispose());
Assert.IsFalse(new Foo(mockBar.Object).AreThereIntegers());
}
public interface IBar
{
IEnumerable<int> Integers { get; }
}
public class Foo
{
private IBar _bar;
public Foo(IBar bar)
{
_bar = bar;
}
public bool AreThereIntegers()
{
return _bar.Integers.Any();
}
}
Upvotes: 4
Reputation: 40576
It does not work because the Any()
method is not directly exposed by the IEnumerable<T>
interface, but it is defined as an extension method on Enumerable
.
I don't think you can set up a call to Any()
on any mock, because it is essentially a static method.
In this case I think it's preferable to use an instance of IEnumerable<int>
(ex: an int array) that can be set up to be empty/non-empty, depending on what you are testing.
Upvotes: 1