Reputation: 32221
I am new to C# mocking, I am trying to read some code and I got one of the tests failing, can you please explain to me what the below source code is trying to test and when will it fail?
Mock<StreamWriter> _streamWriterMock;
string[] expectedLines;
.
.
.
foreach (var line in expectedLines)
{
_streamWriterMock.Verify(a => a.Write(line), Times.Exactly(1));
}
Upvotes: 2
Views: 6377
Reputation: 13765
Verify
You might want to check that the method under test was called, or even how many times that method was called
Just to reproduce the issue try this code
class Program
{
static void Main(string[] args)
{
var _streamWriterMock = new Mock<StreamWriter>("output.txt");
string[] expectedLines= new []{"test","test"};
foreach (var expectedLine in expectedLines)
{
_streamWriterMock.Object.Write(expectedLine);
}
foreach (var line in expectedLines)
{
_streamWriterMock.Verify(a=>a.Write(line),Times.Exactly(1));
}
}
}
In fact, if you try to mock your code with the array {"test","test"}
you will get an exception
Expected invocation on the mock exactly 1 times, but was 2 times: a => a.Write("test")
But if your array is something like the following
string[] expectedLines= new []{"test","test1"};
Your mock will be executed correctly
So your verify
will check if your method is called exactly once for the same input.
I think that the code main goal is to omit that you write the same output twice.
Upvotes: 6
Reputation: 247098
Given the mocked StreamWriter
At best the foreach
loop being used to verify with the mock that the each string in the expected lines array was called on the mocked stream writer's Write
method exactly once during the exercising of the subject under test.
The test will fail if any of the expected lines are written more than once.
Review Moq: Quickstart - Verification
Take the following class as an example of a possible subject that depends on a StreamWriter
public class SubjectUnderTest {
private StringWriter stringWriter;
public SubjectUnderTest(StringWriter stringWriter) {
this.stringWriter = stringWriter;
}
public void WriteLines(string[] lines) {
foreach (var line in lines) {
this.stringWriter.Write(line);
}
}
}
The dependency would be mocked when testing and the functionality of the method under test can be verified in isolation.
For example.
[TestMethod]
public void TestMethod1() {
//Arrange
var _streamWriterMock = new Mock<StringWriter>();
string[] expectedLines = new[] { "line1", "line2" };
var subject = new SubjectUnderTest(_streamWriterMock.Object);
//Act
subject.WriteLines(expectedLines);
//Assert
foreach (var line in expectedLines) {
_streamWriterMock.Verify(a => a.Write(line), Times.Exactly(1));
}
}
If however, expectedLines
had duplicates like { "lineN", "lineN" }
Then the above test would fail as the verification is expecting the Write
method to be called exactly one time with a given string value.
Upvotes: 0
Reputation: 3703
The test in your example iterates through all of the strings in your expectedLines array and checks that _streamWriterMock.Write(string value) is called on each of them exactly once. It will fail if Write is not called or is called more than once on any of the strings.
Update
Generally mocked methods must be virtual and depending on your mocking framework, the mock's method may need to be setup before being called so it may not be a valid test at all since StreamWriter is a concrete class and Write is not a virtual method.
Upvotes: 0