鉴于此功能参考
void ParseFirstTwoRows(FileQueue file, ref string[] firstRow, ref string[] secondRow);
如何使用Moq构建依赖firstRow和secondRow具有值的测试?
我试过这个:
Mock<IFileParser> mockFileParse = new Mock<IFileParser>();
string[] firstline = new string[2] { "1", "2" };
string[] secondline = null;
mockFileParse.Setup(m => m.ParseFirstTwoRows(It.IsAny<FileQueue>(), ref firstline, ref secondline))
.Callback<FileQueue, string[], string[]>((fq, fl, sl) =>
{
fq = new FileQueue();
fl = firstline;
sl = secondline;
});
return mockFileParse;
但这会导致错误:
无效的回调。使用参数设置方法 (FileQueue,String []&amp;,String []&amp;)无法使用参数调用回调 (开fileQueue,字符串[],字符串[])。
我已经看到了几个这方面的问题,但我很困惑,我正在尝试做的是不可能的,或者我是否只是没有正确地构建测试。我测试所需的只是确保ref参数在执行代码中有一个值。
答案 0 :(得分:0)
您不需要回电话。只需确保在调用SUT时使用相同的ref参数,否则调用将失败。
使用示例代码作为参考,查看以下示例
[TestClass]
public class FileParserTest : MiscMoqTests {
[TestMethod]
public void Moq_With_Ref_Arguents() {
//Arrange
Mock<IFileParser> mockFileParse = new Mock<IFileParser>();
// ref arguments
string[] firstline = new string[2] { "1", "2" };
string[] secondline = null;
// Only matches if the ref arguments to the invocation are the same instance
mockFileParse.Setup(m => m.ParseFirstTwoRows(It.IsAny<FileQueue>(), ref firstline, ref secondline)).Verifiable();
var sut = new MyDummyClass(mockFileParse.Object);
//Act
sut.DoSomethingWithRef(ref firstline, ref secondline);
//Assert
mockFileParse.Verify();
}
public class MyDummyClass {
private IFileParser fileParser;
public MyDummyClass(IFileParser fileParser) {
this.fileParser = fileParser;
}
public void DoSomethingWithRef(ref string[] firstRow, ref string[] secondRow) {
var fq = new FileQueue();
fileParser.ParseFirstTwoRows(fq, ref firstRow, ref secondRow);
}
}
public interface IFileParser {
void ParseFirstTwoRows(FileQueue file, ref string[] firstRow, ref string[] secondRow);
}
public class FileQueue { }
}
但是,如果您无法为ref提供相同的实例,那么看起来您将无法成功通过模拟。看看Quick Start for Moq,了解它的功能。
答案 1 :(得分:0)
我通过做一些重构来解决这个问题。虽然Moq在这种情况下不支持ref参数,但它确实可以使用out参数。
这是重构的函数签名:
void ParseFirstTwoRows(FileQueue file, out string[] firstRow, out string[] secondRow);
这是测试设置:
string[] first = { "'one'", "'two'", "'three'" };
string[] second = { "'one'", "'two'", "'three'" };
Mock<IFileParser> mockFileParse = new Mock<IFileParser>();
mockFileParse.Setup(m => m.ParseFirstTwoRows(It.IsAny<FileQueue>(), out first, out second)).Verifiable();
现在,当您尝试测试依赖于ParseFirstTwoRows
的函数时,mock将为out
参数提供两个指定的变量。
答案 2 :(得分:0)
我看到你通过使用参数而不是ref参数解决了你的问题。
但是更改生产代码不是解决方案,您可以使用Typemock隔离器,它允许使用ref参数创建测试:
[TestMethod,Isolated]
public void Mocking_With_Ref_Arguments()
{
// Arrange
string[] first = { "'one'", "'two'", "'three'" };
string[] second = { "'one'", "'two'", "'three'" };
FileQueue file = new FileQueue();
var classUnderTest = new Class1();
// What you will set as ref parameters in this line will return as you call the method
Isolate.WhenCalled(() => classUnderTest.ParseFirstTwoRows(file, ref first, ref second)).IgnoreCall();
// Act
string[] retFirst = null;
string[] retSecond = null;
classUnderTest.someMethod(file, ref retFirst, ref retSecond);
// Assert
CollectionAssert.AreEquivalent(first, retFirst);
CollectionAssert.AreEquivalent(second, retSecond);
}