In an attempt to follow the DRY (Don't Repeat Yourself) principle in my unit tests I am trying to create a generic unit test that will perform the same test on several methods that all return an object which share the same interface. However, I cannot seem to find a way to create a mock.Setup for the methods in the generic method. Examples are as follows:
Here are the class Implementations:
public class RootClass
{
public Foo Foo { get; set; }
}
public class Foo
{
public Bar1 Method1(int x)
{
var bar = new Bar1();
// do stuff //
return bar;
}
public Bar2 Method2(string str)
{
var bar = new Bar2();
// do stuff //
return bar;
}
}
public interface IBar
{
string Message { get; set; }
bool Success { get; set; }
Exception ex { get; set; }
}
public class Bar1 : IBar
{
public string Result { get; set; }
public Exception ex { get; set; }
public string Message { get; set; }
public bool Success { get; set; }
}
public class Bar2 : IBar
{
public int Result { get; set; }
public Exception ex { get; set; }
public string Message { get; set; }
public bool Success { get; set; }
}
Here are the test implementations:
private static RootClass systemUnderTest;
private static Mock<IFoo> FooMock;
[TestInitialize]
public void Setup()
{
FooMock = new Mock<IFoo>();
systemUnderTest = new RootClass();
systemUnderTest.Foo = FooMock.Object;
}
[TestMethod]
public void Method1_Bar1SuccessIsTrue()
{
//FooMock.Setup(x => x.Method1(It.IsAny<int>())).Returns(new Bar1); <~~~~This is the Moq Setup I would like to move into the generic method
AssertBarSuccessIsTrue<int, Bar1>(systemUnderTest.Bar1, FooMock.Object.Bar1);
}
[TestMethod]
public void Method2_Bar2SuccessIsTrue()
{
//FooMock.Setup(x => x.Method2(It.IsAny<string>())).Returns(new Bar2);
AssertBarSuccessIsTrue<string, Bar2>(systemUnderTest.Bar2, FooMock.Object.Bar2)
}
private void AssertBarSuccessIsTrue<PARAM, BAR>(Func<PARAM, BAR> f, Func<PARAM, IBAR> task) where BAR : IBAR where PARAM : new()
{
FooMock.Setup(x => task); <~~~Throws an ArgumentException; no doubt because of the missing lambda expression.
PARAM parameter = new PARAM();
BAR bar = f.Invoke(parameter);
Assert.IsTrue(bar.Success);
}
I have tried to make this work through several attempts including creating an argument for the lambda expression, creating an argument for the It.IsAny<>() expression, creating delegates for the specified method under test. However, every attempt either creates a compiler error or throws a runtime exception.
I can create the generic test if I do a setup in every test (as seen in the commented out .Setup lines). However does anyone have an idea how I can move that setup line into the generic method? I know its only one line, but it seem to me this should be possible.
Related
Context:
I want to test whether a piece of code that purports to layer some operations on top of an IQueryable<T> actually does so. But when I start with code that is known to work, and try to write a test to exercise it, I get an unintelligible error.
Actual Question:
I would like to understand that error, what it means, and why it is happening.
Not an X-Y questions!!
I'm not interested here in what the best way to achieve my original goal is, or whether this test would have achieved it. I'm asking that question separately (link). In this question, I genuinely want to know "what does this error even mean, and why is it happening for code that I know fundamentally works".
Error Message:
System.ArgumentException : Expression of type '' cannot be used for parameter of type
'System.Linq.IQueryable`1[ADH.Web.API.Tests.Services.QueryableTest+DemoDomainModel]' of method
'System.Linq.IQueryable`1[ADH.Web.API.Tests.Services.QueryableTest+DemoViewModel]
Select[DemoDomainModel,DemoViewModel](System.Linq.IQueryable`1[ADH.Web.API.Tests.Services.QueryableTest+DemoDomainModel],
System.Linq.Expressions.Expression`1[System.Func`2[ADH.Web.API.Tests.Services.QueryableTest+DemoDomainModel,ADH.Web.API.Tests.Services.QueryableTest+DemoViewModel]])'
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection`1& arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Queryable.Select[TSource,TResult](IQueryable`1 source, Expression`1 selector)
at ADH.Web.API.Tests.Services.QueryableTest.DemoService.GetAllDemoViewModels() in C:\Work\ADH\ADH\Actuarial Data Hub\ADH.Web.API.Tests\Services\QueryableTest..cs:line 50
at ADH.Web.API.Tests.Services.QueryableTest.CheckQueryableCompiles() in C:\Work\ADH\ADH\Actuarial Data Hub\ADH.Web.API.Tests\Services\QueryableTest..cs:line 71
Simplification of first line:
System.ArgumentException : Expression of type '' cannot be used for parameter of type
'IQueryable`1[DemoDomainModel]' of method
'IQueryable`1[DemoViewModel] Select[DemoDomainModel,DemoViewModel]
(IQueryable`1[DemoDomainModel], Expression`1[Func`2[DemoDomainModel,DemoViewModel]])'
Code and Test that causes the bug (Classes + unit Test)
using System.Linq;
using NUnit.Framework;
using FakeItEasy;
namespace ADH.Web.API.Tests.Services
{
public class QueryableTest
{
public class DemoDomainModel
{
public int Id { get; set; }
public string Reference { get; set; }
public int ChildId { get; set; }
public DemoChildDomainModel Child { get; set; }
}
public class DemoChildDomainModel
{
public int Id { get; set; }
public string ChildReference { get; set; }
}
public class DemoViewModel
{
public int Id { get; set; }
public string Reference { get; set; }
public string ChildReference { get; set; }
}
public interface IDemoRepository
{
IQueryable<DemoDomainModel> GetAllDemos();
}
public class DemoService
{
private readonly IDemoRepository _demoRepository;
public DemoService(IDemoRepository configRepository)
{
_demoRepository = configRepository;
}
public IQueryable<DemoViewModel> GetAllDemoViewModels()
{
var demos = _demoRepository.GetAllDemos();
return demos.Select(demo => new DemoViewModel()
{
Id = demo.Id,
Reference = demo.Reference,
ChildReference = demo.Child.ChildReference
});
}
}
private DemoService _demoService;
private IDemoRepository _fakeDemoRepository;
[SetUp]
public void Setup()
{
_fakeDemoRepository = A.Fake<IDemoRepository>();
_demoService = new DemoService(_fakeDemoRepository);
}
[Test]
public void CheckQueryableCompiles()
{
_demoService.GetAllDemoViewModels();
}
}
}
Say I have this object
public class foo
{
Ibar data {get; set;}
}
public interface Ibar
{
int id { get; set; }
}
public class bar : Ibar
{
public int id {get; set;}
public string a {get; set;}
}
public class bar2 : Ibar
{
public int id {get; set;}
public DateTime b {get; set;}
}
Now I implement a method like this one here
public something Method(foo f)
{
if(f.data is bar)
Console.WriteLine(((bar)f.data).doSomething());
else
Console.WriteLine(((bar2)f.data).doSomething());
}
public string doSomething(this bar b)
{
return b.a;
}
public string doSomething(this bar2 b)
{
return b.b.ToString();
}
So far so good (see). Is there a way to make this part here more elegant? in particular if I have more than one implementations of Ibar, it gets messy...
if(f.data is bar)
Console.WriteLine(((bar)f.data).doSomething());
else
Console.WriteLine(((bar2)f.data).doSomething());
UPDATE
So doSomething should be an extension method. That's why it isn't defined in the interface. So in other words: Im not allowed to change the interface or their implementations.
Are you trying to make dedicated extention class?
assuming you are doing so.
however you can achieve your goal with dynamic
public static class BarExtensions
{
public static string Something(this Ibar b)
{
return doSomething((dynamic)b);
}
public static string doSomething( bar b)
{
return b.a;
}
public static string doSomething(bar2 b)
{
return b.b.ToString();
}
}
so, you will required to call Something only, with Proper Type.
Here Type can be easily get by .GetType() of any object (so it won't be a problem)
I think you can do the type checks in one place because this is a good candidate for polymorphism. Since both bar and bar2 implement Ibar, you can change the definition of doSomething to the following.
public string doSomething(Ibar item)
{
return item is bar ? ((bar)item).a : ((bar2)item).b.ToString();
}
Now when you want to display it, this is how you handle your foo:
public void Method(foo f)
{
Console.WriteLine(f.data);
}
You just pass in the data property because the doSomething will know what to do with it when it receives it.
Update
Based on your comment, I'm expanding the code to use pattern matching as I suggested. Consider the following
public string doSomething(Ibar item)
{
switch (item)
{
case bar b:
return b.a;
case bar2 b:
return b.b.ToString();
case barX b:
return b.X.ToString();
default:
return item.GetType().ToString(); // Just in case...
}
}
where the definition of barX is
public class barX : Ibar
{
public int id {get; set; }
public object X {get; set; }
}
So whenever you add an implementation of Ibar, you cater for it in doSomething. All client code will remain unchanged because all they have to do is pass an Ibar to the doSomething method which uses pattern matching in the last example to determine what type the item is and it acts accordingly.
Final Edit
Seeing as you want to use overloads, you can use reflection but I don't know if that will qualify for your definition of elegant. In this case, it will not use switch statements and will find your methods as long as they are in the type this one is written in. Consider the following and change the defintion of my previously supplied DoSomething.
public static string ProcessThings(Ibar item)
{
var theType = item.GetType();
Console.WriteLine(theType.Name);
MethodInfo method = typeof(Program).GetMethods()
.Where(x => x.IsStatic && x.Name == "DoSomething" && x.ToString().Contains(theType.Name))
.SingleOrDefault();
var ret = method.Invoke(null, new object[] { item });
return ret?.ToString();
}
public static string DoSomething(barX item)
{
return "foo";
}
public static string DoSomething(bar2 item)
{
return "bar";
}
This way, you call the ProcessThings method (renamed for brevity but it can still stay as DoSomething) and it will figure out which one of your overloads to call.
If I remember well you can play with generic type constraints like this:
public something Method<T>(T f) where T : IBar
{
//Stuff here, where assures you f is always IBar
}
This should force the incoming parameter to be of the type you want.
This is the most elegant way I could think of.
Other are typeof and other conditional statements, which would require more in-method code anyway (if, else and so on).
EDIT:
Since OP seems having a hard time to understand I wrote a fully working code sample with Microsoft Unit Testing result.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests_ALL
{
[TestClass]
public class UnrelatedTests
{
[TestMethod]
public void InterfaceTest()
{
bar x = new bar { result = "Hi bar it's " };
bar2 xx = new bar2 { beforeResult = DateTime.Now };
Console.WriteLine(Method(x));
Console.WriteLine(Method(xx));
}
public string Method<T>(T f) where T : Ibar
{
return f.result;
}
}
public class foo
{
public foo(Ibar fooBar)
{
data = fooBar;
}
Ibar data { get; set; }
}
public interface Ibar
{
int id { get; set; }
string result { get; set; }
}
public class bar : Ibar
{
public int id { get; set; }
public string result { get; set; }
}
public class bar2 : Ibar
{
public int id { get; set; }
public DateTime beforeResult
{
set { result = value.ToString(); }
}
public string result { get; set; }
}
public static class Extensions
{
public static string doSomething(this bar b)
{
return b.result;
}
public static string doSomething(this bar2 b)
{
return b.result;
}
}
}
Here's the output:
I am trying to populate an array of objects that inherit from IFoo. The problem I am facing is that structure map is populating the property within IFoo with the same instance of IBar. I cannot add AlwaysUnique() to IBar because this is used elsewhere in our enterprise application and would have consequences.
Is there anyway that I can get it to create new instances of the Bar object for every Foo in the collection?
public interface IFoo
{
IBar bar { get; set; }
}
public class Foo1 : IFoo
{
public IBar bar { get; set; }
public Foo1(IBar bar) { this.bar = bar; }
}
public class Foo2 : IFoo
{
public IBar bar { get; set; }
public Foo2(IBar bar) { this.bar = bar; }
}
public interface IBar
{
Guid id { get; set; }
}
public class Bar : IBar
{
public Guid id { get; set; }
public Bar() {this.id = Guid.NewGuid();}
}
class Program
{
static void Main(string[] args)
{
var container = new Container(_ =>
{
_.Scan(x =>
{
x.TheCallingAssembly();
x.AddAllTypesOf<IFoo>();
});
_.For<IBar>().Use<Bar>(); //I can't change this line because Bar is used elsewhere in the project
});
var foos = container.GetAllInstances<IFoo>();
if (foos.ElementAt(0).bar == foos.ElementAt(1).bar)
throw new Exception("Bar must be a different instance");
}
}
You could do this with a custom policy. See example 3 here, you could adapt that to your needs.
Something like:
public class BarUniqueForFoo : IInstancePolicy
{
public void Apply(Type pluginType, Instance instance)
{
if (pluginType == typeof(IBar) && instance.ReturnedType == typeof(Bar)
{
instance.SetLifecycleTo<UniquePerRequestLifecycle>();
}
}
}
I am trying to make my method generic and I am stuck at a point and need your assistance. The code scenario is I have an abstract class say MyBaseAbs which contains common properties:
public abstract class MyBaseAbs
{
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
public string CommonProp3 { get; set; }
}
Now I have child classes:
public class Mychild1: MyBaseAbs
{
public string Mychild1Prop1 { get; set; }
public string Mychild1Prop2 { get; set; }
public string Mychild1Prop3 { get; set; }
}
and another child class:
public class Mychild2: MyBaseAbs
{
public string Mychild1Prop1 { get; set; }
public string Mychild2Prop2 { get; set; }
}
Now I have to create a common method which needs to perform some operations on the basis of Mychild1 and Mychild2, so what I did is:
public MyCustomClass SaveOperation<T>(T myObj)
where T : MyBaseAbs
{
SaveObject obj = new SaveObject();
}
so inside this method I need to write common code which does the mapping for SaveObject object according to the child object passed. How can I determine which object is passed and use properties accordingly.
One option would be to create a base Save function in your base class and make it virtual.
Then override the method in your child classes. This way when you call the Save method in your SaveOperation it should call the appropriate method from the correct child class.
public abstract class MyBaseAbs
{
public string CommonProp1 { get; set; }
public string CommonProp2 { get; set; }
public string CommonProp3 { get; set; }
public virtual void Save() { }
}
public class Mychild1: MyBaseAbs
{
public string Mychild1Prop1 { get; set; }
public string Mychild1Prop2 { get; set; }
public string Mychild1Prop3 { get; set; }
public override void Save() {
//Implementation for Mychild1
}
}
public class Mychild2: MyBaseAbs
{
public string Mychild1Prop1 { get; set; }
public string Mychild2Prop2 { get; set; }
public override void Save() {
//Implementation for Mychild2
}
}
If you can't modify your business objects, you can check the type of the concrete class in the SaveOperation method:
public MyCustomClass SaveOperation<T>(T myObj)
where T : MyBaseAbs
{
SaveObject obj = new SaveObject();
if (myObj is Mychild1) {
Mychild1 mychild1 = (Mychild1) myObj;
// Business logic for object of type Mychild1
} else if (myObje is Mychild2) {
Mychild2 mychild2 = (Mychild2) myObj;
// Business logic for object of type Mychild2
}
}
Notice that this is not a very solid solution as, if you are creating new objects that implement your abstract class, you will have to remeber to add another branch in the if statement.
As #BojanB mentioned, the obvious solution would be to create a virtual method in your base class and override it in the derived, but if you cannot modify the code there then you can create a method for each derived class and create a dictionary that maps each type to its method:
private Dictionary<Type, Action<MyBaseAbs, MyCustomClass>> _saveOperations =
new Dictionary<Type, Action<MyBaseAbs, MyCustomClass>>();
//You can then set an entry for each of your derived classes
_saveOperations[typeof(Mychild1)] = (myObj, myCustomObj) =>
{
//Mychild1-specific logic
};
public MyCustomClass SaveOperation(MyBaseAbs obj)
{
//do the common saving operations here
var result = new MyCustomClass();
//....
var actualType = obj.GetType();
if(_saveOperations.ContainsKey(actualType))
{
_saveOperations[actualType](obj, result);
}
return result;
}
You can then add an item to the dictionary for each derived class. It is the same concept as using the is operator but allows you to add methods for more derived types without modifying the original SaveOperation method
You can use C#'s As-Operator as follows:
Mychild1 child1 = myObj as Mychild1;
if(child1 != null) {
//Here you can use child1.Mychild1Prop1 forexample
}
Link to msdn: https://msdn.microsoft.com/en-us/library/cscsdfbt.aspx
I have the following:
public abstract class FooBase
{
public virtual int Id { get; set; }
}
public class Foo1 : FooBase { /* could be stuff here */ }
public class Foo2 : FooBase { /* could be stuff here */ }
public class Bar
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual SOMETHING WhichFoo { get; set }
}
...where WhichFoo deals with which FooBase to use (potentially string of "Foo1" but this seems quite messy).
With mappings:
public class FooBaseMap : ClassMap<FooBase>
{
public FooBaseMap()
{
this.Id(x => x.Id);
this.DiscriminateSubClassesOnColumn("Type");
}
}
public class Foo1Map : SubclassMap<Foo1>
{
public Foo1Map() { this.DiscriminatorValue("Foo1"); }
}
public class Foo2Map : SubclassMap<Foo2>
{
public Foo2Map() { this.DiscriminatorValue("Foo2"); }
}
What I want to be able to do is to create a new Foo, either 1 or 2, based on a value stored in Bar. So:
Bar bar = this.Session.Get<Bar>(1);
FooBase foo1 = bar.GetANewFoo(); // returns a new Foo1
Bar anotherBar = this.Session.Get<Bar>(123);
FooBase foo2 = bar.GetANewFoo(); // returns a new Foo2
Where GetANewFoo() could be a method, a property which returns an empty instance of Foo1 or Foo2.
Effectively what I want to do is to store the type of FooBase to be created by GetANewFoo in Bar.
What's the best way of going about this without explicitly having to manually write "Foo1" or "Foo2" to a Bar when I create one?
You can create a column in the Bar table which is going to save what kind of Foo it is. So, if this SOMETHING type of property is an enum, or a string, or an int (whatever), you can use switch-case statement to identify the kind of Foo, create what you need and return.
Just like this:
public FooBase GetANewFoo()
{
switch (WhichFoo)
{
case "Foo1": return new Foo1();
case "Foo2": return new Foo2();
default: return null;
}
}
Okay I think I got it - actually rehashing a method I used for the Strategy Pattern.
public abstract class FooFactoryBase
{
protected FooFactoryBase() { } // for NHibernate
protected FooFactoryBase(Guid id)
{
this.Id = id;
}
public virtual Guid Id { get; set; }
public virtual IList<Bar> Bars { get; set; }
public abstract FooBase CreateFoo();
}
public class Foo1Factory : FooFactoryBase
{
public readonly static Guid Guid = new Guid("abc123...");
public Foo1Factory() : base(Guid) { }
public override FooBase CreateFoo()
{
return new Foo1();
}
}
Then Bar becomes:
public class Bar
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual FooFactoryBase FooFactory { get; set; }
}
And mappings:
public class BarMap : ClassMap<Bar>
{
this.Id(x => x.Id);
this.Map(x => x.Name);
this.References(x => x.FooFactory);
}
public class FooFactoryBaseMap : ClassMap<FooFactoryBase>
{
this.Id(x => x.Id);
this.HasMany(x => x.Bars).Inverse();
this.DiscriminateSubClassesOnColumn("Id");
}
public class Foo1FactoryMap : SubClassMap<Foo1Factory>
{
this.DiscriminatorValue(Foo1Factory.Guid);
}
Now when I create my database I can populate it with all my FooFactorys, when adding Bars I can just load the appropriate Factory from the database and then call my code like so:
Bar bar = this.Session.Get<Bar>(10);
FooBase foo = bar.FooFactory.CreateFoo();
and the appropriate FooBase will be created.
Sometimes you just need to ask the question to figure it out :)