用最小起订量模拟方法并使 moq.Object 在那里可用
Mock a Method with Moq and make moq.Object available there
代码结构和 classes 来自这个主题:
这是我的总结。
我有以下 Interface
:
public interface IPosition
{
// Some properties here which must be accessed in CalcValueChangeAtDate method.
int Size { get; }
...
double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate);
}
我在 class RealPosition
中实现了这样的接口:
public class RealPosition : IPosition
{
/* IPosition implementation */
public double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate)
{
return CalcValueChangeAtDate(this, fromDate, toDate);
}
/* I created this static method with the idea to use the for mocked objects.
* This way I would need to implement the logic only once and use it with real
* and mocked objects*/
public static double CalcValueChangeAtDate(IPosition pos, DateTime fromDate, DateTime toDate)
{
// Logic here must access properties of IPosition
}
}
此外,我创建了另一个使用 IPosition
接口的 class:
public class EquityCurveBuilder
{
private static DataSeries CalcEquityCurve(List<IPosition> posDict)
{
DateTime fromDate;
DateTime toDate;
foreach (IPosition pos in posDict)
{
/* Here I want to call the implementation of IPosition.
* However in my unit test posDict is a List of mocked IPositons.
* Simply because I don't have another choice. */
double stockVal = pos.CalcValueChangeAtDate(fromDate, toDate);
// Do something with stockVal
}
}
}
我的测试设置如下所示:
[Test]
public void RecalcOriginalEquityCurve()
{
// Here I get a list of mocked IPositions
List<IPosition> Positions = ImporterTools.GetPositions(FilePath, FullPositionsCsv);
// Execute Test
DataSeries equityCurve = EquityCurveBuilder.BuildEquityCurve(Positions);
// Evaluate test results
...
}
public class ImporterTools
{
public static List<IPosition> GetPositions(string path, string fileName)
{
// Import raw data and create a mocked IPosition
Mock<IPosition> tmpPosMoq = new Mock<IPosition>();
tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
Returns( ??? );
// Create a List and return it
}
}
问题是,在单元测试中,我所有的都是模拟职位。但是 CalcEquityCurve()
方法调用了 IPostion
的 CalcValueChangeAtDate()
。为了正确测试 CalcEquityCurve()
,CalcValueChangeAtDate()
必须 return 有效值。 return 值取决于方法的参数。因此,模拟对象调用 static
方法 RealPosition.CalcValueChangeAtDate()
.
的想法
现在我被 ???
困住了。我根本不知道在那里写什么,以便在我调用时调用 RealPosition
class 中的 static
方法:
tmpPosMoq.Object.CalcValueChangeAtDate(fromDate, toDate);
有可能吗?
感谢您的帮助!
康斯坦丁
回答你的问题,我想这就是你要问的:
tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
Returns( (DateTime dtfrom, DateTime dtto) =>
{
return RealPosition.CalcValueChangeAtDate(tmpPosMoq.Object, dtfrom, dtto);
});
但这完全没有意义。这只是调用实际实现的一种复杂而令人费解的方式,就像您没有模拟它一样。单元测试用于测试业务逻辑。 Mocking 用于提供虚假但真实的值,这些值通常来自无法进行实际单元测试的东西——数据库调用、Web 服务调用等。
很有可能你在这里有东西...
// Logic here must access properties of IPosition
...是嘲笑的候选人。但是我没有看到你的构造函数中有任何依赖项,所以我什至无法猜测。
代码结构和 classes 来自这个主题:
这是我的总结。
我有以下 Interface
:
public interface IPosition
{
// Some properties here which must be accessed in CalcValueChangeAtDate method.
int Size { get; }
...
double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate);
}
我在 class RealPosition
中实现了这样的接口:
public class RealPosition : IPosition
{
/* IPosition implementation */
public double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate)
{
return CalcValueChangeAtDate(this, fromDate, toDate);
}
/* I created this static method with the idea to use the for mocked objects.
* This way I would need to implement the logic only once and use it with real
* and mocked objects*/
public static double CalcValueChangeAtDate(IPosition pos, DateTime fromDate, DateTime toDate)
{
// Logic here must access properties of IPosition
}
}
此外,我创建了另一个使用 IPosition
接口的 class:
public class EquityCurveBuilder
{
private static DataSeries CalcEquityCurve(List<IPosition> posDict)
{
DateTime fromDate;
DateTime toDate;
foreach (IPosition pos in posDict)
{
/* Here I want to call the implementation of IPosition.
* However in my unit test posDict is a List of mocked IPositons.
* Simply because I don't have another choice. */
double stockVal = pos.CalcValueChangeAtDate(fromDate, toDate);
// Do something with stockVal
}
}
}
我的测试设置如下所示:
[Test]
public void RecalcOriginalEquityCurve()
{
// Here I get a list of mocked IPositions
List<IPosition> Positions = ImporterTools.GetPositions(FilePath, FullPositionsCsv);
// Execute Test
DataSeries equityCurve = EquityCurveBuilder.BuildEquityCurve(Positions);
// Evaluate test results
...
}
public class ImporterTools
{
public static List<IPosition> GetPositions(string path, string fileName)
{
// Import raw data and create a mocked IPosition
Mock<IPosition> tmpPosMoq = new Mock<IPosition>();
tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
Returns( ??? );
// Create a List and return it
}
}
问题是,在单元测试中,我所有的都是模拟职位。但是 CalcEquityCurve()
方法调用了 IPostion
的 CalcValueChangeAtDate()
。为了正确测试 CalcEquityCurve()
,CalcValueChangeAtDate()
必须 return 有效值。 return 值取决于方法的参数。因此,模拟对象调用 static
方法 RealPosition.CalcValueChangeAtDate()
.
现在我被 ???
困住了。我根本不知道在那里写什么,以便在我调用时调用 RealPosition
class 中的 static
方法:
tmpPosMoq.Object.CalcValueChangeAtDate(fromDate, toDate);
有可能吗?
感谢您的帮助! 康斯坦丁
回答你的问题,我想这就是你要问的:
tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
Returns( (DateTime dtfrom, DateTime dtto) =>
{
return RealPosition.CalcValueChangeAtDate(tmpPosMoq.Object, dtfrom, dtto);
});
但这完全没有意义。这只是调用实际实现的一种复杂而令人费解的方式,就像您没有模拟它一样。单元测试用于测试业务逻辑。 Mocking 用于提供虚假但真实的值,这些值通常来自无法进行实际单元测试的东西——数据库调用、Web 服务调用等。
很有可能你在这里有东西...
// Logic here must access properties of IPosition
...是嘲笑的候选人。但是我没有看到你的构造函数中有任何依赖项,所以我什至无法猜测。