I've broken a lot of my unit tests when I've added some more includes as I'm not using Lazy Loading in EF. Before my Mock was setup line this:
mockDocRepo.Setup(
x => x.GetBy(It.IsAny<Expression<Func<Doctor, bool>>>(), It.IsAny<Expression<Func<Doctor, object>>>()))
.Returns(stubDoctor);
Which worked fine for a single include however adding another include when calling GetBy breaks all my tests. For example:
var doctor = _dbContextScope.Repository<Doctor>().GetBy(x => x.Id == DoctorId, y => y.Contracts, y => y.Leave.Select(x => x.Type));
I've tried changing my Moq setup to accept an array e.g It.IsAny<Expression<Func<Doctor, object>>[]>() however this doesn't seem to work. I also tried just adding the second include in the setup
e.g
mockDocRepo.Setup(
x => x.GetBy(It.IsAny<Expression<Func<Doctor, bool>>>(), It.IsAny<Expression<Func<Doctor, object>>>(),It.IsAny<Expression<Func<Doctor, object>>>()))
.Returns(stubDoctor);
It seems to be the .Select(x => x.Type) in the final include that breaks everything.
Any ideas on how to fix this would be great.
I don't think can do a MOQ setup Linq Enumerable.Select method. It is a static method on Enumerable class.
Using Moq, you cannot mock/setup on static methods, .In order to setup it has to be a virtual method.
Alternatively try to abstract DbContext and wrap the .select in a virtual method. Then you should be able to do the setup.
Related
I'm not sure if I should work directly with the EntityObject, or if I should make som wrapper methods for selecting, updating and deleting EntityObjects? I would like to use the last option, but I can't really figure out how to return an EntityObject (so I still can call context.SaveChanges();) and not for example a List<Worker> (which is stupid since I can't make changes to the Workers in the list and then easily submit the chages to the database.
For example, I have a Worker table. I could get a worker by using my context:
var worker = context.Worker.Where(w => w.WorkerID == 1).FirstOrDefault();
Or, I could create a wrapper method:
public static RETURNTYPE GetWorkerByID(int id, context)
{
var worker = context.Worker.Where(w => w.WorkerID == 1).FirstOrDefault();
return worker;
}
What kind of returntype should I work with, if I still wish to work with the context (allowing me to alter the data)?
Thanks!
If you make a wrapper type you will not be able to use it with context anymore. Using wrapper means that your return type will represent a new instance filled from the entity object and when you push that instance back you will again need to create / fill entity object to work with.
Have you considered using POCOs (EF 4.0 and newer only)? That would solve your problem because there is on EntityObject base class.
I have this code in my project, how can I use Moq to moq the documentsession and setup the return value?
_session.Query<IPageModel, PageByUrl>()
.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(x => x.Metadata.Url == virtualUrl);
This is what I have tried before I asked
var session = new Mock<IDocumentSession>();
var pageModel = new DummyModel();
session.Setup(x => x.Query<IPageModel, PageByUrl>()
.Customize(y => y.WaitForNonStaleResultsAsOfLastWrite())
.FirstOrDefault(y => y.Metadata.Url == path)).Returns(pageModel);
This throws an exception and I can't figure out how to change the moq
System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.Query<IPageModel,PageByUrl>().Customize(y => y.WaitForNonStaleResultsAsOfLastWrite()).FirstOrDefault<IPageModel>(y => y.Metadata.Url == .path)
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b()
at Moq.Mock.Setup(Mock mock, Expression`1 expression, Func`1 condition)
at Moq.Mock`1.Setup(Expression`1 expression)
at BrickPile.Tests.Web.Routing.PathResolverTests.Home_Page_With_Default_Action(String path) in PathResolverTests.cs: line 26
Instead of mocking the document session, have you thought about using the embeddabledocumentstore? It could run completely in memory and you have the full database as backend for your tests.
See also this blog post which describes some of the backgrounds: http://novuscraft.com/blog/ravendb-and-the-repository-pattern
This question inspired a blog post.
The short answer: Don't. You're coupling your application to RavenDB and violating the Interface Segregation Principle. Instead, write a custom interface that specifies precisely what services your class (the system under test) needs. Write a wrapper class that implements that and delegates to RavenDB. This might use the Repository Pattern, or it might be something simpler. Your interface should be simple to mock.
You need to mock whatever IDocumentSession.Query() returns as a separate mock so that you can then setup the customize call. I'm typing this on my phone so I can't easily give you an example.
I have an interface that includes a member that looks like:
void ExecuteSqlCommand(string procedureName, SqlParameter[] parameters);
I am using FakeItEasy to create a mock of this to pass to one of my classes.
The code I am testing calls this method, then checks the value of one of the SqlParameters. How do I use FakeItEasy to set the Value property of this parameter when the method is called?
I appreciate that this is probably not the best practice for getting individual pieces of information out of a database, but I am working with existing stored procedures, some of which have OUT parameters.
As you say, this is probably not the best practice. That aside, I guess you could do something like this:
A.CallTo(() => fake.ExecuteSqlCommand(A<string>._, A<SqlParameter[]>._))
.Invokes((string s, SqlParameter[] p) => p[someIndex].Value = yourValue);
Or, using a less-readable but more powerful overload, access a IFakeObjectCall directly:
A.CallTo(() => fake.ExecuteSqlCommand(A<string>._, A<SqlParameter[]>._))
.Invokes(callObject => callObject.GetArgument<SqlParameter[]>("parameters")[someIndex].Value = yourValue);
We have two Assemblies that contain their own Entity-Framework EDMX & repositoriy objects. These are registered using Autofac in an ASP.NET webapplication.
These Assemblies are very similar of architecture (but differing EDMX) we have found that the last EntityConnection being registered is the EntityConnection that is being used in both Assemblies. We need to limit the usage of an EntityConnection to only be used by Types of an assembly or namespace.
var assembly = typeof(Activity).Assembly;
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
builder.Register(reg => new EntityConnection(ConnectionString));
var assembly = typeof(User).Assembly;
builder.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
builder.Register(reg => new EntityConnection(ConnectionString));
Is there a way to register the EntityConnection and limit the depth of EntityConnection? Limit each EntityConnection to the assembly it belong to?
Here's a pseudocode example of how we want to register EntityConnection for use in only an assembly or namespace.
builder.Register(reg => new EntityConnection(ConnectionString)).ForNamespace("x");
try to solve the problem at an higher level of abstraction. Since you have two separate domains (one containing the Activity entity, and one containing the User entity), it would be convenient to have this explicitly in your application design. For instance, define a factory of some kind per domain:
public interface IActivityDomainContextFactory
{
ObjectContext CreateNew();
}
public interface IPeopleDomainContextFactory
{
ObjectContext CreateNew();
}
You can now easily create an implementation for each interface, register them in the Autofac ContainerBuilder and let your services depend on one of those interfaces, instead of depending them on a EntityConnection.
In this case you of course still have a dependency on the Entity Framework itself (see here for how to abstract that away), but this makes your configuration much easier, less fragile, better performing, and your application code more maintainable.
I hope this helps.
You probably want to name/key your registrations. See TypedNamedAndKeyedServices - Autofac
I think this solves half your problem, how to register the types. The other half is in the resolution. Since your doing autoregistration via assembly scanning, this might take a little more trickery.
There are plenty of good suggestions out there on improving this, so just recording my solution as a general sketch of how you'd do this in Autofac.
The trick is to use named services for the connections, then customise parameter resolution for types in each assembly so that the EntityConnection parameters get a named instance:
builder.Register(reg => new EntityConnection(ConnectionString))
.Named<EntityConnection>("activities");
builder.RegisterAssemblyTypes(typeof(Activity).Assembly)
.AsImplementedInterfaces()
.WithParameter(
(pi, c) => pi.ParameterType == typeof(EntityConnection),
(pi, c) => c.ResolveNamed<EntityConnection>("activities"));
builder.Register(reg => new EntityConnection(ConnectionString))
.Named<EntityConnection>("users");
builder.RegisterAssemblyTypes(typeof(User).Assembly)
.AsImplementedInterfaces()
.WithParameter(
(pi, c) => pi.ParameterType == typeof(EntityConnection),
(pi, c) => c.ResolveNamed<EntityConnection>("users"));
I want to inject DispatcherNotifiedObservableCollection into (and only into) all ViewModels (located in MyProject.ViewModels) as ObservableCollection.
With Ninject I can accomplish this with:
Bind(typeof(ObservableCollection<>))
.To(typeof(DispatcherNotifiedObservableCollection<>))
.When(context => context.ParentContext.Binding
.Service.Namespace == "MyProject.ViewModels");
I've learned from Nicholas Blumhardt: Autofac vs Ninject contextual binding?
that Autofac does not provide this functionality, but some workaround could be applied.
Thanks!
(sorry for my English)
Edit 1: Changed title for better description.
Edit 2, 3: Changed contents and title for better description.
Sorry about the slow reply.
Your best bet with Autofac is to use a rule for registering the ViewModels and to apply a parameter to resolve the different implementation of ObservableCollection<>:
// Default for other components
builder.RegisterGeneric(typeof(ObservableCollection<>));
// Won't be picked up by default
builder.RegisterGeneric(typeof(DispatcherNotifiedObservableCollection<>))
.Named("dispatched", typeof(ObservableCollection<>));
var viewModelAssembly = typeof(AViewModel).Assembly;
builder.RegisterAssemblyTypes(viewModelAssembly)
.Where(t => t.Name != null && t.Name.EndsWith("ViewModel"))
.WithParameter(
(pi, c) => pi.ParameterType.IsClosedTypeOf(typeof(ObservableCollection<>)),
(pi, c) => c.ResolveNamed("dispatched", pi.ParameterType));
You'll need to be using Autofac; for IsClosedTypeOf(). Also, if the version of Autofac you're using doesn't support this overload of WithParameter() you can use the overload that takes a Parameter and pass a ResolvedParameter instead.
Hope this helps,
Nick