I have a class with properties in it that are populated via a loader class. Quick example:
class Employee : IEmployee
{
public string EmpFirstName {get; set}
public string EmpLastName {get; set}
}
public class EmpLoader(int employeeID)
{
public void Load(IEmployee emp)
{
emp.EmpFirstName = //lookup the employee using the EmployeeID
//...
}
}
I'm wondering how to go about arranging things so that a mocked EmpLoader's Load() method fills in particular values in the Employee. Something like:
Employee myEmp = new Employee();
_empLoader = new Mock<EmpLoader>();
_empLoader.Setup(empL => empL.Load(myEmp)).Sets_myEmp_Properties_Somehow();
I've used Moq's Setup() method before when deciding what sort of return values come back, but wasn't sure if I can use it or another method to set properties in one class via a third party class. Could be I'm way off here; I'm not an expert in Moq and am open to suggestions.
You can use the Callback() method on the Setup() to load the data:
Employee myEmp = new Employee();
Mock<EmpLoader> _empLoader = new Mock<EmpLoader>();
_empLoader.Setup(empL => empL.Load(myEmp)).Callback<IEmployee>((emp) => {
emp.EmpFirstName = "Steve";
// ... Load all properties
}
Related
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.
Just a little idea I'm playing with, not sure if it's viable or has much of a use.
I'm trying to generate a very basic EF Code First database using the Roslyn CTP.
Code:
var scriptEngine = new ScriptEngine(new[] { "System", "System.Core", typeof(DbContext).Assembly.Location });
var session = Roslyn.Scripting.Session.Create();
var t = scriptEngine.CompileSubmission<DbContext>(#"
using System.Data.Entity;
public class Car {
public int Id {get; set;}
public string Name {get; set; }
}
public class Context : DbContext {
public DbSet<Car> Cars {get; set; }
}
new Context();
", session);
t.Execute();
When executed I get the following exception
Exception:
The type 'Submission#0+Car' was not mapped. Check that the type has not been explicitly excluded by using the Ignore method or NotMappedAttribute data annotation. Verify that the type was defined as a class, is not primitive, nested or generic, and does not inherit from EntityObject.
Looking through the list of possible issues, I'm guessing that Roslyn is making a nested class as part of the code gen. This makes sense otherwise the "new Context();" call would need to be wrapped into a class/method of some sort. I could emit an assembly, which would confirm the above but likely wouldn't have any clues on how to write it correctly.
I also went down the route of Syntax.ClassDeclaration, but ended up with a few hundred lines of code just to make a class with 1 property and no obvious way how to instantiate that class.
Question
Is there an easy way to create a class in Roslyn that is publicly accessible (eg not nested in another class)?
You can use Roslyn to create actual DLL library that contains your type based on your source code and then use that from your script:
var classCode = #"
using System.Data.Entity;
public class Car {
public int Id { get; set; }
public string Name { get; set; }
}
public class Context : DbContext {
public DbSet<Car> Cars { get; set; }
}";
var syntaxTree = SyntaxTree.ParseCompilationUnit(classCode);
var compilation = Compilation.Create(
"car",
new CompilationOptions(assemblyKind: AssemblyKind.DynamicallyLinkedLibrary))
.AddReferences(
new AssemblyFileReference(typeof(object).Assembly.Location), // mscorlib
new AssemblyFileReference(typeof(Uri).Assembly.Location), // System
new AssemblyFileReference(typeof(IOrderedQueryable<>).Assembly.Location), // System.Data
new AssemblyFileReference(typeof(DbContext).Assembly.Location) // EntityFramework
)
.AddSyntaxTrees(syntaxTree);
var dllPath = "car.dll";
using (var stream = File.OpenWrite(dllPath))
{
compilation.Emit(stream);
}
var code = #"new Context();";
var scriptEngine = new ScriptEngine(new[] { new FileInfo(dllPath).FullName, "EntityFramework" });
var context = scriptEngine.Execute<DbContext>(code);
Consider the following snippet;
public enum ReportType {Monthly,Quarterly}
public class BaseReport
{
public ReportType ReportType {get;set;}
}
public class MonthlyReport : BaseReport
{
public String month = "January"
public MonthlyReport() { ReportType = Monthly;}
}
public class Foo
{
public virtual void AddReport(BaseReport report);
}
[Test]
public void Test1()
{
var mock = new Mock<Foo>(){CallBase =true};
var report = new MonthlyReport();
mock.Object.AddReport(report);
}
Well I am trying to verify if the AddReport() is called with certain parameter here;
mock.Verify(x => x.AddReport(It.Is<MonthlyReport>(p => p.month == "January" &&
p.ReportType == ReportType.Monthly)));
As I feared, it doesn't work with a MonthlyReport parameter for Is<> even though it is derived from BaseReport. If I use Is,then I can't use p.month in the expression, and I am not that proficient with c# to know whether I can use if(p is MonthlyReport) in a lambda expression or more importantly, it would work as intended.
How can I approach this problem? Please note that the mock is partial, Although I can live with
Setup approach with callbacks if it is neatly solves my problem.
Any pointers would be greatly appreciated...
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.
I have a class like:
public class Store
{
public Store()
{
Products = new List<Product>();
}
public IList<Product> Products {get; private set;}
public void AddProduct(int id, string productCode)
{
Product p = new Product();
p.Id = id;
p.ProductCode = productCode;
//Validate before adding
Products.Add(p); //How can i verify that this was called
}
}
Using Moq how can i verify that the Add method of the Products List was called? Can someone provide a simple example?
Well you can't really mock anything at the moment as the Products list is set up in the default constructor?
The easiest thing to do would be to assert against your products collection manually (i.e. just verify there's a product in there with the specified ID and Code) then you don't have to worry about mocking at all.
If you really want to use Moq to test this you need to provide a means to inject your Mock and get around your constructor, as an example you can provide two constructors
public class Store {
public Store() : this(new List<Product>()) {
}
public Store(IList<Product> productList) {
Products = productList
}
//Implementation
}
You can then write a test against your add method as follows
[Test]
public AddProduct_WithIdAndProductCode_AddsProductToCollection() {
int productId = 0;
string productCode = "a";
var productListMock = new Mock<IList<Product>>();
Store store = new Store(productListMock.Object);
store.AddProduct(productId, productCode);
productListMock.Verify(pl =>
pl.Add(It.Is<Product>(p =>
p.Id == productId && p.ProductCode == productCode)));
}
Do you need to test that add was called or that the list now has the expected number of items?
Assert.True(store.Products.Count == 1);