Can I make fun of Objectresult <T> for Entity Framework using MOQ

I am using Entity Frameowrk 4.0 and I call a stored procedure that returns an ObjectResult, and I tried to use MOQ and could not mock ObjectResult. Could anyone mock ObjectResult with moq? A.

TIA Yaz

+4
source share
4 answers

I have this problem too; I use the database design and the EF 4.x DbContext Generator template to create my DbContext.

I change the context generator in the following ways:

  • Instead of DbSet <T> for object sets, I return IDbSet <T>; this allows me to use InMemoryDbSet <T> for unit testing (Google for implementation);
  • Instead of ObjectResult <T> for stored procedures, I return an IEnumerable <T>. Inside the virtual method created for the stored procedure, I load the ObjectResult <T> into the list <T> and return this;
  • Finally, I retrieve an interface that displays entity objects and import functions. This means that I can then make fun of the whole DbContext for ultra-fast unit tests. You should still write integration tests, which, of course, test the functionality of the database.
+4
source

ObjectResult ( as per MSDN docs ) is a private class, so you cannot mock it. The way to use Mocking libraries like Moq is that when you do something like

Mock<Foo> fooMock = new Mock<Foo>(); 

It generates (using Reflection.Emit and various other magic tricks) a class that looks a bit like this

 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 } } 

i.e. It requires a class (interface) that you want to execute Mock and subclasses (or implements it in the case of an interface). This allows you to use a device that allows you to check whether a method has been called or returns a specific value (this supports various configuration and verification methods). Limitations on this method of bullying: -

  • Sealed classes (not subclasses)
  • Private members (not available from subclass)
  • Methods or classes of properties that are not virtual (and therefore cannot be overridden).

One method you can take when approaching private classes is to wrap them with some kind of interface, which is Mockable. Alternatively, you can try the Mock interface, which implements a sealed class that consumes only your code.

+2
source

ObjectResult is commonly used with Linq, so it is mainly used as IEnumerable. Although the object is sealed, you can make fun of it and customize the behavior of IEnumerable.

Here is an example code where TResult is the result type of the stored procedure, and TDbContext is the DbContext, and it returns 1 element.

 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); 

You can add any values ​​to the array in the example above or use any other collection (you only need an enumerator).

Try this code. It works for me with EF 6.1.2 and Moq 4.2

0
source

I could not find a way to mock the private class and wanted to verify that the parameters of the stored procedure match the entity model. Here is my solution:

  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); } } } } 
0
source

Source: https://habr.com/ru/post/1310891/


All Articles