用Moq模拟方法并在那里使moq.Object可用 [英] Mock a Method with Moq and make moq.Object available there
问题描述
此主题中出现了代码结构和类: C#模拟具有内部属性设置器的类
The code structure and classes emerge from this topic: C# Mock a Class With an Internal Property Setter
这是我所拥有的摘要.
我有以下Interface
:
public interface IPosition
{
// Some properties here which must be accessed in CalcValueChangeAtDate method.
int Size { get; }
...
double CalcValueChangeAtDate(DateTime fromDate, DateTime toDate);
}
我在类RealPosition
中实现了接口,如下所示:
And I implemented the interface in the class RealPosition
like this:
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
接口的类:
Further I created another class which uses the IPosition
interface:
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()
必须返回有效值.返回值取决于方法的参数.因此,模拟对象调用static
方法RealPosition.CalcValueChangeAtDate()
的想法.
The problem is, that in the unit test all I have are mocked positions. But the CalcEquityCurve()
method invokes CalcValueChangeAtDate()
of IPostion
. In order to test CalcEquityCurve()
properly, CalcValueChangeAtDate()
must return valid values. The return value depends on the arguments of the method. Hence the idea that the mocked object invokes the static
method RealPosition.CalcValueChangeAtDate()
.
现在,我坚持使用???
.我根本不知道在那写什么,所以我在调用时调用RealPosition
类的static
方法:
Now I am stuck with the ???
. I simply don't have any idea what to write there so that my static
method from the RealPosition
class gets called when I call:
tmpPosMoq.Object.CalcValueChangeAtDate(fromDate, toDate);
有可能吗?
谢谢您的帮助! 康斯坦丁
Thank you for your help! Konstantin
推荐答案
要回答您的问题,我想这就是您要的内容:
To answer your question, I think this is what you are asking for:
tmpPosMoq.Setup(v => v.CalcValueChangeAtDate(It.IsAny<DateTime>(), It.IsAny<DateTime>())).
Returns( (DateTime dtfrom, DateTime dtto) =>
{
return RealPosition.CalcValueChangeAtDate(tmpPosMoq.Object, dtfrom, dtto);
});
但这是完全没有意义的.这只是调用实际实现的一种复杂而复杂的方式,与您没有模拟它的方式完全相同.单元测试用于测试业务逻辑.模拟是为了提供虚假但现实的值,这些值通常来自无法进行单元测试的东西,例如数据库调用,Web服务调用等.
But this is completely pointless. It is just a complex and convoluted way to call actual implementation that would be the exact same as if you did not mock it. Units tests are for testing business logic. Mocking is for providing fake but realistic values that would normally come from something that cannot be practically unit tested - database calls, web service calls, etc.
您在这里拥有的东西很有可能...
It is much more likely that something you have in here...
// Logic here must access properties of IPosition
...是模拟的候选人.但是我看不到构造函数中有任何依赖项,因此我什至无法猜测.
... is a candidate for mocking. But I do not see any dependencies being taken in your constructor so I can't even guess.
这篇关于用Moq模拟方法并在那里使moq.Object可用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!