我正在使用Entity Frameowrk 4.0,我打電話給一個存儲過程返回一個ObjectResult,我試圖使用MOQ並且無法模擬ObjectResult。有沒有人能夠使用moq模擬ObjectResult?我可以嘲笑Objectresult <T>使用MOQ的實體框架
TIA 雅緻
我正在使用Entity Frameowrk 4.0,我打電話給一個存儲過程返回一個ObjectResult,我試圖使用MOQ並且無法模擬ObjectResult。有沒有人能夠使用moq模擬ObjectResult?我可以嘲笑Objectresult <T>使用MOQ的實體框架
TIA 雅緻
ObjectResult(according to the MSDN docs)是密封類作爲這樣你不能模擬它。懲戒庫,例如起訂量的工作方式是,當你這樣做
Mock<Foo> fooMock = new Mock<Foo>();
它生成(使用Reflection.Emit的和其他各種魔術)一類,看起來有點像這樣
public class FooMockingProxy : Foo {
public override void This() {
// Mocking interceptors to support Verify and Setup
}
public override string That() {
// Mocking interceptors to support Verify and Setup
}
}
即它需要你想要的類(接口)模擬和子類化(或者在接口的情況下實現它)。這使得它可以放入允許它檢查一個方法是否被調用的儀表,或者返回一個特定的值(這支持各種Setup和Verify方法)。到嘲笑的這種方法的限制是: -
接近密封類時可以採用的一種技術是將它們包裝在某種可摹擬的接口中。或者,您可以嘗試並模擬密封類實現的接口,只有您的代碼消耗。
我也有這個問題;我使用數據庫優先設計,EF 4.x DbContext生成器模板來生成我的DbContext。
我修改上下文的生成在以下幾個方面:
讓你想知道MS何時會意識到這種事情需要通過接口而不是具體的類來暴露。 Grr .... – 2014-08-11 07:57:09
ObjectResult通常與Linq一起使用,因此它主要用作IEnumerable。即使對象被封閉,你也可以模擬它並設置IEnumerable行爲。
以下是一些示例代碼,其中TResult是存儲過程結果類型,TDbContext是DbContext,它將返回1個項目。
var valueEnumerator = new TResult[] { new TResult() }.GetEnumerator();
var mockStoredProcedure = new Mock<ObjectResult<TResult>();
mockStoredProcedure.Setup(x => x.GetEnumerator()).Returns(valueEnumerator);
var mockEntities = new Mock<TDbContext>();
mockEntities.Setup(x => x.[stored procedure method]()).Returns(mockStoredProcedure.Object);
您可以添加任何值,例如在陣列上方或使用任何其他集合(你只需要枚舉)。
試試這段代碼。它適用於EF 6.1.2和Moq 4.2
我找不到一種方法來模擬一個密封的類,並且想要測試存儲過程的參數是否與實體模型相匹配。這裏是我的解決方案:
namespace CardiacMonitoringTest
{
[TestClass]
public class CardiacMonitoringDataTest
{
[TestMethod]
public void TestEntityStoredProcedure()
{
List<string> SPExceptions = new List<string>();
SPExceptions.Add("AfibBurdenByDay");
SPExceptions.Add("GetEventTotalsByCategory");
EntitiesCon db = new EntitiesCon();
foreach (MethodInfo mi in typeof(EntitiesCon).GetMethods())
{
string ptype = mi.ReturnType.Name;
if (ptype.IndexOf("ObjectResult") > -1)
{
List<SqlParameter> ExtractedParameters = SPListParm(ConfigurationManager.ConnectionStrings["CardiacMonitoring"].ConnectionString, mi.Name);
ExtractedParameters = ExtractedParameters.Where(a => a.ParameterName != "@RETURN_VALUE" && a.ParameterName != "@TABLE_RETURN_VALUE").ToList();
ParameterInfo[] EntityParameters = mi.GetParameters();
if ((from b in SPExceptions where b.ToLower() == mi.Name.ToLower() select b).Count() > 0)
{
continue;
}
foreach (ParameterInfo pi in EntityParameters)
{
try
{
Assert.IsTrue(
(from a in ExtractedParameters where pi.Name.ToLower() == a.ParameterName.Replace("@", "").ToLower() select a).Count() == 1);
}
catch (Exception ex)
{
Trace.WriteLine("Failed SP:" + mi.Name + " at parameter:" + pi.Name);
throw (ex);
}
try
{
Assert.IsTrue(EntityParameters.Count() == ExtractedParameters.Count());
}
catch (Exception ex)
{
Trace.WriteLine("Failed SP:" + mi.Name + " on parameter count:" + EntityParameters.Count() + " with detected count as:" + ExtractedParameters.Count());
throw (ex);
}
}
}
}
}
private List<SqlParameter> SPListParm(string ConnectionString, string SPName)
{
try
{
SqlConnection conn = new SqlConnection(ConnectionString);
SqlCommand cmd = new SqlCommand(SPName, conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlCommandBuilder.DeriveParameters(cmd);
SqlParameter[] prmDetectParameters = new SqlParameter[cmd.Parameters.Count];
cmd.Parameters.CopyTo(prmDetectParameters, 0);
List<SqlParameter> toReturn = new List<SqlParameter>();
toReturn.AddRange(prmDetectParameters);
return (toReturn);
}
catch (Exception ex)
{
Trace.WriteLine("Failed detecting parameters for SP:" + SPName);
throw (ex);
}
}
}
}
您是否介意進一步擴展?這看起來像一個代碼轉儲。 – 2016-09-06 13:35:16
這是一個單元測試,通過將ADO.NET連接與反射與實體框架模型進行比較,測試所有存儲過程參數與數據庫中的實際內容是否匹配。它回答我的實體模型是否與數據庫匹配。 – 2018-01-11 14:33:39
你可以舉一個例子來說明如何加載這個模擬ObjectResult的值? – KevinDeus 2011-10-05 23:01:14