Is it possible to change the NUnit test name convention on the entire fixture instead of on the test by test basis? - nunit

I want to use the template "{m}({1})". Now I can provide TestName = "{m}({1})" in each and every TestCase attribute. But this is too many repetitions. The TestFixture also has this parameter, but using it does not seem to have any effect:
[TestFixture(TestName = "{m}({1})")]
public class Tests
{
...
}
My question - is it possible to change the test name convention for all the tests in the given fixture by specifying it just once instead of in each and every TestCase attribute?
EDIT 1
I would like to keep using the TestCase attribute, even though using TestCaseSource does allow me to specify the template only once.

You can avoid setting name in each and every TestCase attribute by using TestCaseSource and TestCaseData as below example:
[TestFixture]
public class UnitTest1
{
[TestCaseSource(typeof(MyDataClass), nameof(MyDataClass.TestCases))]
public void DivideTest(int n, int d)
{
Assert.AreEqual(3, n / d);
}
}
public class MyDataClass
{
public static IEnumerable TestCases
{
get
{
yield return new MyTestCaseData(9, 3);
yield return new MyTestCaseData(30, 10);
yield return new MyTestCaseData(12, 4);
}
}
}
public class MyTestCaseData : TestCaseData
{
public MyTestCaseData(object arg1, object arg2) : base(arg1, arg2)
{
SetName("{m}({1})");
}
}
The SetName method of TestCaseData allows setting the name of an individual test case. So creating a new class derived from TestCaseData and setting name in constructor will avoid setting name for each TestCase attributes and also makes code cleaner.
Solution 2: (Without using TestCaseSource and TestCases)
It cannot be possible using TestFixture TestName property and using TestCase attribute natively. But same result can be achieved by creating and using custom attribute, for example MyTestCaseAttr - a class inherited from TestCaseAttribute and setting name in its constructor (there by avoiding to set name each time)
[TestFixture]
public class UnitTest1
{
[MyTestCaseAttr(12, 4)]
public void DivideTest(int n, int d)
{
Assert.AreEqual(3, n / d);
}
[MyTestCaseAttr(4, 5, 6)]
public void AddTest(int a, int b, int c)
{
Assert.AreEqual(15, a + b + c);
}
}
public class MyTestCaseAttr : TestCaseAttribute
{
public MyTestCaseAttr(object arg1, object arg2) : base(arg1, arg2)
{
TestName = "{m}({1})";
}
public MyTestCaseAttr(object arg1, object arg2, object arg3) : base(arg1, arg2, arg3)
{
TestName = "{m}({1})";
}
}

No, that's not possible. Using the TestName property as you have done simply sets the name of the test suite represented by the fixture class. In this case, the new name is "{m}({1})", which is used as-is, without making any substitutions.
The reason for this is that the special sequences used in a name template only apply to naming test cases, not to fixtures.
If you run using the NUnit3 console runner, you may specify a name format for use on all test cases in the assembly through the --test-name-format option.

Related

Extract strongly-typed data context instance from arbitrary query

Background
We have a class library which has a grid (inherits from WPF DataGrid) with refresh functionality. The grid has a IQueryable Query property, which enables the refresh. Each grid's query is defined not in the class library, but in the referencing end-project:
var dg = new RefreshableDataGrid();
dg.Query = () => new ProjectDbContext().Persons;
Each grid also has a textbox for text filtering. When text is entered in the filter, an expression is generated which checks if any string property or string-convertible property (using SqlFunctions.StringConvert) contains the filter string. The expression is then appended to the original query as an argument to Where, and thus only the records containing matching strings are returned.
//within the class library
//pseudo-code -- this is actually done via reflection, because at compile time the
//actual type of the grid is not known, and there is no generic placeholder
this.ItemsSource = this.Query.Where(filterExpression)
In some cases, the filter logic is defined in end-projects, on the entity type. For example:
public interface IFilterable {
public Expression<Func<String, Boolean>> TextSearchExpression();
}
public class Email {
public int ID {get;set;}
public int PersonID {get;set;}
public string Address {get;set;}
}
public class Person : IFilterable
public int ID {get;set;}
public string LastName {get;set;}
public string FirstName {get;set;}
public Expression<Func<String, Boolean>> TextSearchExpression() {
Dim ctx = new ProjectDbContext();
return phrase => LastName.Contains(phrase) || FirstName.Contains(phrase) ||
ctx.Emails.Where(x => x.PersonID = ID && x.Address.Contains(prase).Any();
}
}
This expression tree uses an instance of the project-specific context, which is a different instance from that of the original query. Queries cannot use components from multiple contexts (at least not in Entity Framework). I can rewrite the expression tree to use a specific instance, but I need to extract the original instance from the query.
It seems obvious that the query holds some reference to the context instance, otherwise the query would not be able to return results.
I do not want to pass the context instance to the class library.
Hence:
Given a query, how can I get the strongly-typed DbContext instance used to create the query?
In other words, what goes in the body of this method:
DbContext GetDbContext<TSource>(IQueryable<TSource> qry) {
// ???
}
It seems obvious that the query holds some reference to the context instance, otherwise the query would not be able to return results.
That's true, but it's implementation specific detail and in EF is encapsulated inside internal members/classes/interfaces.
Also taking into account that DbContext is build on top of the ObjectContext, holding a reference to the DbContext is not strongly necessary. Fortunately that's not the case :)
The following uses reflection and implementation details of the latest EF6.1.3 (tested and working if you don't use some 3rd party extensions like LinqKit and similar that replace the query provider):
public static DbContext GetDbContext<TSource>(this IQueryable<TSource> query)
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
var provider = query.Provider;
var internalContextProperty = provider.GetType().GetProperty("InternalContext", flags);
if (internalContextProperty == null) return null;
var internalContext = internalContextProperty.GetValue(provider, null);
if (internalContext == null) return null;
var ownerProperty = internalContext.GetType().GetProperty("Owner", flags);
if (ownerProperty == null) return null;
var dbContext = (DbContext)ownerProperty.GetValue(internalContext, null);
return dbContext;
}
I would recommend passing an instance of MyDataContext into your query function
public class DACPerson
{
public static IQueryable<Person> GetAllAsQueryable(MyDataContext db)
{
return db.People.AsQueryable();
}
}
This allows you to do the following in the calling function:
public List<Person> UpdateListofPeople(string term)
{
using(DataContext db = new DataContext())
{
var people = DACPerson.GetAllAsQueryable(db);
var result = people.Where(x=>x.Username.Contains(term)).
//call other Data Access Component FUnctions here using same DB....
}
}
i.e. you can bring the filtering to the layer above the data access class.
Some people may not like to do this. You may get the advice that its best to keep all entityframeowrk functionality within the same layer and just return the DTO. I like the above approach though. It depends on who will have to maintain each part of your application in the future.
Hope this helps at least

In Autofac, how do I propagate Keys through Adapters

I'm using the adapter support in Autofac to convert multiple types to a desired type. I also want to preserve the keys/names/metadata attached to the adapter input types, so that they exist with the same values on the adapter output types - this is needed for using IIndex<,> to resolve instances by name.
I can't figure out how to propagate the keys/names/metadata through the adapter function, since the adapter function runs during component construction, and the metadata needs to be propagated when the container is built.
Here's an example xunit test, which fails:
/// <summary>
/// Unit test to figure out how to propagate keys through adapters.
/// </summary>
public sealed class AutofacAdapterTest
{
public class A
{
public A(string key)
{
Key = key;
}
public string Key { get; private set; }
}
public class B
{
public B(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class C : B
{
public C(string name)
: base(name)
{}
}
public class LookerUpper
{
private readonly IIndex<string, B> _bIndex;
public LookerUpper(IIndex<string, B> bIndex)
{
_bIndex = bIndex;
}
public B LookupByName(string name)
{
return _bIndex[name];
}
}
[Fact]
public void TestPropagateKeysThroughAdapters()
{
var builder = new ContainerBuilder();
// Register named types
builder.RegisterType<A>().Named<A>("A").WithParameter("key", "A");
builder.RegisterType<B>().Named<B>("B").WithParameter("name", "B");
builder.RegisterType<C>().Named<C>("C").Named<B>("C").WithParameter("name", "C");
// Adapter to convert an A to a B, since it's not a subclass
builder.RegisterAdapter<A, B>((c, a) => new B(a.Key));
// Register LookerUpper, which is the only top-level type that needs to be autowired
builder.RegisterType<LookerUpper>();
var container = builder.Build();
var lookerUpper = container.Resolve<LookerUpper>();
// Test expected results
Assert.Equal("A", lookerUpper.LookupByName("A").Name);
Assert.IsType<B>(lookerUpper.LookupByName("A")); // A should have been adapted to a B
Assert.Equal("B", lookerUpper.LookupByName("B").Name);
Assert.IsType<B>(lookerUpper.LookupByName("B"));
Assert.Equal("C", lookerUpper.LookupByName("C").Name);
Assert.IsType<C>(lookerUpper.LookupByName("C"));
Assert.Throws<ComponentNotRegisteredException>(() => lookerUpper.LookupByName("D"));
}
}
The statement lookerUpper.LookupByName("A") fails with a ComponentNotRegisteredException, because the name value "A" is not propagated through the adapter function (which adapts A -> B ). If the first two lines of Asserts are commented out, the rest of the test works as expected.
I found a workable solution to this problem by using Autofac Metadata instead of Autofac keys or names. For the call to RegisterAdapter<TFrom, TTo>(Func<TFrom,TTo>), metadata is propagated from the IComponentRegistration for TFrom to the IComponentRegistration for TTo; however the keys/names are not propagated. The omission of keys may be a bug or by design, I'll file a bug with autofac to figure out which is the case and follow up.
The unfortunate part about using metadata is I can't use an IIndex<string, B> constructor parameter, so I had to use an IEnumerable<Meta<Lazy<B>>> parameter and create my own dictionary of string -> Lazy<B> to provide similiar functionality to IIndex. Here's the code that works:
/// <summary>
/// Unit test to figure out how to propagate keys through adapters.
/// </summary>
public sealed class AutofacAdapterTest
{
internal const string LookupKey = "lookup";
public class A
{
public A(string key)
{
Key = key;
}
public string Key { get; private set; }
}
public class B
{
public B(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class C : B
{
public C(string name)
: base(name)
{}
}
public class LookerUpper
{
private readonly IDictionary<string, Lazy<B>> _bLookup;
public LookerUpper(IEnumerable<Meta<Lazy<B>>> bMetas)
{
_bLookup = bMetas.ToDictionary(meta => meta.Metadata[LookupKey].ToString(), meta => meta.Value);
}
public B LookupByName(string name)
{
return _bLookup[name].Value;
}
}
[Fact]
public void TestPropagateKeysThroughAdapters()
{
var builder = new ContainerBuilder();
// Register types that will be looked up; attach metadata for the lookup key
builder.Register((c) => new A("A")).WithMetadata(LookupKey, "A");
builder.Register((c) => new B("B")).WithMetadata(LookupKey, "B");
builder.Register((c) => new C("C")).AsSelf().As<B>().WithMetadata(LookupKey, "C");
// Adapter to convert an A to a B, since it's not a subclass
builder.RegisterAdapter<A, B>((c, a) => new B(a.Key));
// Register LookerUpper, which is the only top-level type that needs to be autowired
builder.RegisterType<LookerUpper>();
var container = builder.Build();
var lookerUpper = container.Resolve<LookerUpper>();
// Test expected results
Assert.Equal("A", lookerUpper.LookupByName("A").Name);
Assert.IsType<B>(lookerUpper.LookupByName("A")); // A should have been adapted to a B
Assert.Equal("B", lookerUpper.LookupByName("B").Name);
Assert.IsType<B>(lookerUpper.LookupByName("B"));
Assert.Equal("C", lookerUpper.LookupByName("C").Name);
Assert.IsType<C>(lookerUpper.LookupByName("C"));
Assert.Throws<KeyNotFoundException>(() => lookerUpper.LookupByName("D"));
}
}
It should also be possible to create an IRegistrationSource and some extension methods that extend what is done in RegisterAdapter<TFrom, TTo>, such that the keys in TFrom are propagated to TTo - that would be an ideal solution, but potentially more work to maintain, so I'll probably stick with this.
It was fixed in Autofac version 3.5.1.
Link to the bug
Link to the fix

MVC4 and Entity Framework Inheritance and Include

I have some simple objects
public class DataClass
{
public int id;
public string Data;
}
public class Job()
{
public int id;
}
public class NewJob : Job
{
public DateTime StartDate;
public DataClass data;
}
I have then defined them in my dBContext()
public DbSet<Job> Jobs { get; set; }
public DbSet<DataClass> DataClass { get; set; }
Now if I use the following code
NewJob job = (NewJob) db.Jobs.Find(id);
This works fine but returns "data" as null
I know I define the class with the virtual keyword and it works and populates the "data" object.
public class NewJob : Job
{
public DateTime StartDate;
public virtual DataClass data;
}
But in my case I "normally" do not want the "data" object to be populated. So I need to load it on demand.
If I try something like
NewJob job = (NewJob)db.Jobs.Include("data").First();
I get an exception
A specified Include path is not valid. The EntityType 'Models.Job' does not declare a navigation property with the name 'data'.
I guess this is because it is looking at "job" and not "NewJob" when it is trying to do the include.
I also do not like the include with a string - no design time checking.
It looks like you are trying to convert data object to your domain object via type casting which is a very bad idea. What you want to do is grab your data object, instantiate your domain object, and map your data values to the domain object using some type of helper class. A very helpful tool I have been using is Automapper. Its a tool that will allow you to map one object to another. It also allows the use of regular expression to help with the mappings if the naming conventions between the 2 objects are different.
If you're using Entity Framework Code First and want to create instances of derived classes/entities you should do the following:
using (var db = new MyDbContext())
{
var newJob = db.Jobs.Create<NewJob>();
newJob.data.Data = "some data for a new job"; // this is string Data from DataClass
db.Jobs.Add(newJob);
db.SaveChanges();
}
After a lot of searching I found the following which can help.
If you include the System.Data.Entity namespace in your using clause then you can use the extension method .Include() after OfType<>() which is not normally available.
Slightly different code sample
using System.Data.Entity;
NewJob job = (NewJob)db.Jobs.OfType<NewJob>().Include(m => m.data).Where(x => x.id == id).FirstOrDefault();
This seems to be working for me in the example I used.

How can you generically map a DbDataReader to a Castle.Windsor resolved type?

This is confusing me, so this question will probably be confusing.
I have a an application that uses implementations of an IJob interface to accomplish different tasks.
public interface IJob
{
int Id { get; set; }
string Name { get; set; }
void Run();
}
I am using the Castle.Windsor.WindsorContainer to resolve these implementations, and using the service id to help identify them.
WindsorContainer container = new WindsorContainer(new XmlInterpreter());
IJob jobToExecute = container.Resolve<IJob>("nameOfJob");
I wrote a little generic extension method that simply puts the values of SQL columns into their corresponding properties.
public static void MapTo<T>(this DbDataReader reader, ref T instance) where T : class
{
Type objectType = typeof(T);
foreach (PropertyInfo propertyInfo in objectType.GetProperties())
{
if (propertyInfo.CanWrite)
{
int ordinal = -1;
try
{
ordinal = reader.GetOrdinal(propertyInfo.Name);
object value = reader[ordinal] == DBNull.Value ? null : reader[ordinal];
propertyInfo.SetValue(instance, value, null);
}
catch (IndexOutOfRangeException ex)
{
continue;
}
}
}
}
Now, because you can't instantiate an instance of an interface, passing an IJob to this method won't work. However, in order to gain the benefits of the IoC container, I need to do everything in my repository using the IJob interface. So, I wrote with this to resolve the IJob implementation, and pass it to the MapTo method to populate the necessary properties:
public IJob GetJobById(int id)
{
string cmdTxt = "SELECT Id, Name, Description, DateStarted, ScheduledCompletion, Completed FROM Jobs WHERE Id = #id";
using (DbCommand cmd = _dataFactory.CreateCommand(cmdTxt))
{
_dataFactory.AddParam(cmd, "id", id, DbType.Int32);
using (DbDataReader rdr = cmd.ExecuteReader())
{
if (rdr.Read())
{
IJob job = _container.Resolve<IJob>("job.implementation");
rdr.MapTo<IJob>(ref job);
return job;
}
else
{
return null;
}
}
}
}
Is this an OK design decision? Do you see any problems?
Well, for one, calling methods via reflection is usually not nice... and it looks like you're using Windsor as a type dictionary, which it is not...
I would write a non-generic MapTo (which would take a Type as parameter) that operates on an already-existing instance (when you create a new instance with Activator.CreateInstance you discard the instance Windsor had resolved) and then use it from the ComponentCreatedEvent event in IKernel. Something like this:
container.Kernel.ComponentCreated += (model, instance) => {
if (model.Service == typeof(IJob)) {
// select id,name from jobs where id = model.Name
// use MapTo to fill id,name into instance
}
}

Does MEF Support Customized CTOR?

It looks like that MEF framework creates objects which have default CTOR. How about customized CTOR, or Constructor with parameters? For example:
[Export (typeof(IInterface1))]
public class MyClass : IInterface1
{
public MyClass(int id) {....}
....
}
If not, one way I can think is to pass object as parameters to CTOR. For example:
public Interface IParameterID {
public int Id { get; private set; }
...
}
Then the CTOR will be:
public MyClass([Import(typeof(IParameter))] IParameterID id)
{ ... }
Not sure if it is possible to add attribute to CTOR's parameters? And the next question is that if MEF will automatically create an instance of IParameter and inject it to the CTOR's parameter?
Yes, this is possible. Just put an [ImportingConstructorAttribute] on the constructor you would like to use. The parameters will automatically be treated as imports, but if you need to change the contract name on them you can also put an import attribute on them.