Mocking ChildProperty cannot get it to work? - moq

I am trying to test a property that is nested in a child class.
I always get an error.
Am I missing something?
Is it possible to test a child property in moq.
I have the following
[Test]
public void Should_be_able_to_test_orderCollection()
{
var orderViewMock = new Mock<IOrderView>();
orderViewMock.SetupGet(o => o.Customer.OrderDataCollection.Count).Returns(2);
orderViewMock.SetupSet(o => o.Customer.OrderDataCollection[1].OrderId = 1);
orderViewMock.VerifySet(o => o.Customer.OrderDataCollection[1].OrderId=1);
}
public class CustomerTestHelper
{
public static CustomerInfo GetCustomer()
{
return new CustomerInfo
{
OrderDataCollection = new OrderCollection
{
new Order {OrderId = 1},
new Order {OrderId = 2}
}
};
}
}
public class CustomerInfo
{
public OrderCollection OrderDataCollection { get; set; }
}
public class OrderCollection:List<Order>
{
}
public class Order
{
public int OrderId { get; set; }
}
public interface IOrderView
{
CustomerInfo Customer { get; set; }
}

You can't mock the OrderDataCollection property of CustomerInfo because it's a non-virtual property on a concrete class.
The best way to fix this would be to extract an interface from CustomerInfo and let IOrderView return that instead:
public interface IOrderView
{
ICustomerInfo Customer { get; set; }
}

It is definitely possible if you have the right abstractions. You need to mock your Customer and its children too, for your example to work, like:
var customerMock = new Mock<ICustomer>();
orderViewMock.SetupGet(o => o.Customer).Returns(customerMock.Object);
etc. for the entire hierarchy of child objects you want to control with mocks. Hope it makes sense.
/Klaus

You will get a runtime error, as you've found:
System.ArgumentException: Invalid setup on a non-overridable member:
o => o.Customer.OrderDataCollection.Count
at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo methodInfo)
You can mock the IOrderView and return any CustomerInfo instance you want, but you're also trying to mock CustomerInfo and OrderCollection. As Mark Seemann mentioned, you can only mock interfaces and virtual properties/methods. This will hold true for almost any mocking/isolation framework except for Typemock (commercial).
As others have already stated, one way to solve the problem is to return an interface for the customer.

Related

EF Core with CosmosDB: OwnsOne and OwnsMany throw NullReferenceException

I'm working on a new project that uses CosmosDB and Entity Framework Core (via the Microsoft.EntityFrameworkCore.Cosmos NuGet package, version 5.0.7; the project itself is .NET Core 5). I'm new to both, and running into an issue I can't sort out.
In short, I need to save a complex object to the database. It's a big model that will have multiple collections of classes underneath it, each with their own properties and some with collections underneath them as well. I'm trying to configure EF with OwnsOne and OwnsMany to store these child objects underneath the top-level one. The code compiles, and will save to the database so long as all the owned objects are left empty. But whenever I put anything into an owned object, either with OwnsOne or OwnsMany, I get a pair of NullReferenceExceptions.
I've tried to strip my code down to the very basics. Here's how it currently looks.
Owner and owned classes:
public class Questionnaire
{
// Constructors
private Questionnaire() { }
public Questionnaire(Guid id)
{
Test = "Test property.";
TV = new TestQ();
Id = id;
}
public Guid Id { get; set; }
public string Test { get; set; }
public TestQ TV { get; set; }
// Public Methods
public void AddForm(Form f)
{
// not currently using this method
//Forms.Add(f);
}
}
public class TestQ
{
public TestQ()
{
TestValue = "test ownsone value";
}
public string TestValue { get; set; }
}
DbContext:
public class QuestionnaireDbContext : DbContext
{
public DbSet<Questionnaire> Questionnaires { get; set; }
public QuestionnaireDbContext(DbContextOptions<QuestionnaireDbContext> options) : base(options) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultContainer(nameof(Questionnaires));
modelBuilder.Entity<Questionnaire>().HasKey(q => q.Id);
modelBuilder.Entity<Questionnaire>().OwnsOne(q => q.TV);
}
}
And the code from the service that calls the dbContext (note that this is based on a generic service that I didn't set up originally). The actual exceptions are thrown here.
public virtual TEntity Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
_context.SaveChanges();
return entity;
}
Ultimately I need this to work with OwnsMany and a collection, but I figured it might be simpler to get it working with OwnsOne first. The key thing to note here is that if I comment out the line
TV = new TestQ();
in the Questionnaire class, the model persists correctly into CosmosDB. It's only when I actually instantiate an owned entity that I get the NullReferenceExceptions.
Any advice would be much appreciated! Thank you!
Well, I'm not sure why this is the case, but the issue turned out to be with how we were adding the document. Using this generic code:
public virtual async Task<TEntity> Add(TEntity entity)
{
_context.Entry(entity).State = EntityState.Added;
await _context.SaveChanges();
return entity;
}
was the issue. It works just fine if I use the actual QuestionnaireDbContext class like so:
context.Add(questionnaire);
await context.SaveChangesAsync();

How to specify default property values for owned entity types in Entity Framework Core 2.0?

I have a simple POCO type, say something like
public class OwnedEntity {
public string stringProperty { get; set; }
public decimal decimalProperty { get; set; }
public bool boolProperty { get; set; }
public int intProperty { get; set; }
}
and an actual entity with an OwnedEntity reference
public class SomeEntity {
public string Id { get; set; }
public OwnedEntity OwnedEntity { get; set; }
}
I set up the relationship like described in the documentation using EF Core's Fluent API:
protected override void OnModelCreating (ModelBuilder builder) {
base.OnModelCreating (builder);
builder.Entity<SomeEntity> ().OwnsOne (e => e.OwnedEntity);
}
I can't find anything on how to define default-values for all the properties of OwnedEntity. I tried to initialize the properties like this:
public class OwnedEntity {
public string stringProperty { get; set; } = "initial"
public decimal decimalProperty { get; set; } = -1M;
public bool boolProperty { get; set; } = false;
public int intProperty { get; set; } = -1;
}
but with no effect. Same goes with the [DefaultValueAttribute] (but that was to expect since it's explicitly mentioned).
There's a bit of information on how to handle initial values for regular entities:
modelBuilder.Entity<SomeOtherEntity>()
.Property(e => e.SomeIntProperty)
.HasDefaultValue(3);
But since I'm facing an Owned Entity Type, I can't access the type via Entity<T>.
Is there a way of doing what I'm looking for?
Some things worth mentioning:
I have a solid amount of specific entities where most of them are using the OwnsOne relation
Declaring all OwnedEntity-properties in a base class is not an option since not all the entities have those properties
I`m using EF Core 2.0.3 and ASP.NET Core MVC 2.0.4
Edit:
Originally, I wanted to have newly created SomeEntity instances to come with preset properties for all of the 'embedded' SomeEntity.OwnedEntity properties.
But looking at how my associated controller works, it all makes sense... I have the following methods for the 'Create' operation:
[HttpGet]
public IActionResult Create () {
return View (nameof (Create));
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create (SomeEntity model) {
context.Add (model);
await context.SaveChangesAsync ();
// redirect etc.
}
Which means that no object is created for the [HttGet] overload of Create and all the HTML inputs linked to properties (via asp-for) are initially empty. Okay. So I guess the proper way of doing this is to manually create a new instance of SomeEntity and pass it to the Create view like this:
[HttpGet]
public IActionResult Create () {
return View (nameof (Create), new SomeEntity());
}
Is this the right approach then or are there some more things to keep in mind?
Assuming you understand what EF Core Default Values are for, and just looking for equivalent of Entity<T>().Property(...) equivalent.
The owned entities are always configured for each owner type by using the ReferenceOwnershipBuilder<TEntity,TRelatedEntity> class methods. To access this class you either use the result of OwnsOne method, or use the OwnsOne overload taking second argument of type Action<ReferenceOwnershipBuilder<TEntity,TRelatedEntity>>.
For instance, using the second approach:
builder.Entity<SomeEntity>().OwnsOne(e => e.OwnedEntity, ob =>
{
ob.Property(e => e.stringProperty)
.HasDefaultValue("initial");
ob.Property(e => e.decimalProperty)
.HasDefaultValue(-1M);
// etc.
});

BuildUp method in unity doesn't consider MappingName

I have a strange problem with unity BuildUp method. I have one interface that's mapped to three classes. I have given a name to each mapping.
Now I need to inject the dependency in an existing object (it's an attribute so I don't have control over lifetime). I call the BuildUp method to inject the dependency, but it always throws an exception which says that the interface is not mapped.
If I map the interface to one type only and I remove the mappingname, the BuildUp method works.
If I map the interface to one type only and I specify the mappingname, the BuildUp method fail.
I have tried registering types in configuration and code and nothing changes.
I suspect this is a bug, but I would like to know if anyone else has another idea.
This is how i call buildup method:
var newAttr = _container.BuildUp(myAttribute.GetType(), myAttribute, "Mapping1");
I tried to follow your scenario and this sample works
var container = new UnityContainer();
container.RegisterType<IFoo, One>("1", new InjectionProperty("Bar", "1"));
container.RegisterType<IFoo, Two>("2", new InjectionProperty("Bar", "2"));
container.RegisterType<IFoo, Three>("3", new InjectionProperty("Bar", "3"));
One one = new One();
container.BuildUp(one.GetType(), one, "1");
Assert.AreEqual("1", one.Bar);
public interface IFoo
{
string Bar { get; set; }
}
public class One : IFoo
{
public string Bar { get; set; }
}
public class Two : IFoo
{
public string Bar { get; set; }
}
public class Three : IFoo
{
public string Bar { get; set; }
}
Update
var container = new UnityContainer();
container.RegisterType<Person>(new InjectionProperty("Foo"));
container.RegisterType<IFoo, One>("1");
container.RegisterType<IFoo, Two>("2");
container.RegisterType<IFoo, Three>("3");
Person person = container.Resolve<Person>("1");
Assert.IsNotNull(person.Foo);
Assert.IsInstanceOfType(person.Foo, typeof(One));
public class Person
{
public IFoo Foo { get; set; }
}
I guess this is what you mean? Short answer: That's not the way Unity works.
Long answer: You will have to specify a ResolverOverride that does that for you. But even that is not enough as you want the container to create the value you want to inject for you. So you would need to specify a ResolvedParameter as the value for your ResolverOverride. With Unity's out-of-the-box parts the Resolve would look like this
Person person = container.Resolve<Person>(new PropertyOverride("Foo", new ResolvedParameter(typeof(IFoo), "1")));
Or you can use this custom override instead
public class NamedPropertyOverride : ResolverOverride
{
private readonly string propertyName;
private readonly string registrationName;
public NamedPropertyOverride(string propertyName, string registrationName)
{
this.propertyName = propertyName;
this.registrationName = registrationName;
}
public override IDependencyResolverPolicy GetResolver(IBuilderContext context, Type dependencyType)
{
var currentOperation = context.CurrentOperation as ResolvingPropertyValueOperation;
if (currentOperation != null &&
currentOperation.PropertyName == this.propertyName)
{
Type propertyType = currentOperation
.TypeBeingConstructed
.GetProperty(currentOperation.PropertyName, BindingFlags.Instance | BindingFlags.Public)
.PropertyType;
return new NamedTypeDependencyResolverPolicy(propertyType, this.registrationName);
}
return null;
}
}
Change the line that contains the call to Resolve in the above sample to this one
Person person = container.Resolve<Person>(new NamedPropertyOverride("Foo", "1"));
That should do the trick.

Moq: Return mock object with most implementation created

I want to mock my Repository object in such a way that it can still do actual DB retrieve operations. Only for Saving operations, I wanted to setup to return mock data since I don't want it to save into the DB.
How should I do it?
Thanks.
Maybe you should make your Save operation virtual and override it in a subclass which you use in your tests rather than using Moq?
First of all, your unit tests should never actually go out to the database (it is all right for integration tests, but that is a larger topic). What you want to do is pretty straightforward with Moq, though:
public class MyRepo
{
public virtual string Save(MyClass foo)
{
// perform save...
}
}
public class MyService
{
public MyRepo Repo { get; set; }
public string VerifyAndSave(MyClass foo)
{
// verify foo...
return new Repo.Save(foo);
}
}
public class MyClass()
{
public string SomeData { get; set; }
}
Notice the virtual modifiers on the methods--these are important for Moq to be able to stub them.
In your tests you could then do something like this:
[TestClass]
public class SomeTests
{
private Mock<MyRepo> MockRepo { get; set; }
private MyService Target { get; set; }
[TestInitialize]
public void Setup()
{
MockRepo = new Mock<MyRepo>();
Target = new MyService();
Target.Repo = MockRepo.Object;
}
[TestMethod]
public void MyTest()
{
const string expectedOutput = "SAVED";
MyClass exampleData = new MyClass();
MockRepo.Setup(x => x.Save(It.IsAny<MyClass>())).Returns(expectedOutput);
Target.VerifyAndSave(exampleData);
MockRepo.Verify(x => x.Save(It.IsAny<MyClass>()));
}
}
The chained calls of Setup and Returns in this case would guarantee that the calling method (i.e. VerifyAndSave) would see the value that you specified--"SAVED" in this case.
For more examples, take a look at the Moq quickstart docs.

Bind CheckBoxFor to bool?

How to bind nullable bool to checkbox in MVC 2. I try with this code in view:
<%: Html.CheckBoxFor(model => model.Communication.Before)%>
But show me compilation error.
Thanks in advance.
I know about this issue. You can try to use this workaround:
Create new property called Before in yours ViewModel:
public class YoursViewModel
{
public Communication Communication { get; set; }
public bool Before
{
get
{
bool result;
if (this.Communication.Before.HasValue)
{
result = (bool)this.Communication.Before.Value;
}
else
{
result = false;
}
return result;
}
set
{
this.Communication.Before = value;
}
}
}
Also you have to be careful for Communication property this have to be instanced before use. For example when you initialize ViewModel in controller you also have to initialize this property.
ControllerAction()
{
YoursViewModel model = ViewModelFactory.CreateViewModel<YoursViewModel >("");
model.Communication = new Communication ();
return View(model);
}
Thanks
Ivan Baev
A checkbox can have two states: ckecked/uncheked, true/false, 1/0. So trying to bind a checkbox to a property that could potentially have three states doesn't really fit the picture. I would recommend you adapting your view model so that it uses a non nullable boolean property. If in your domain model you have a nullable boolean which you cannot change you could do this in the mapping layer between your domain model and view model.
One way to bind Checkbox in MVC View
With EF database first, boolean (bit) field in the database produces a nullable bool? Property in the generated class. For demo I have a table named Dude with the fields
Id uniqueidentifier
Name varchar(50)
IsAwesome bit
The following class is generated by EF:
namespace NullableEfDemo
{
using System;
public partial class Dude
{
public System.Guid Id { get; set; }
public string Name { get; set; }
public Nullable<bool> IsAwesome { get; set; }
}
}
To be able to bind IsAwesome to checkbox I simply extend the class Dude. This is to avoid editing the generated class, if I need to refresh it. So I added a code file DudePartial.cs to my project (the name is irrelevant). Don’t forget to declare or using the project namespace:
namespace NullableEfDemo
{
partial class Dude
{
public bool Awesome
{
get { return IsAwesome ?? false; }
set { IsAwesome = value; }
}
}
}
This declares a new property Awesome of type bool that can be bound to the checkbox in the Edit view
#Html.CheckBoxFor(model => model.Awesome, new { #class = "control-label" })
In the HttpPost I’m binding the models Awesome property instead of IsAwesome.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Name,Awesome")] Dude dude)
{…

Resources