I'm trying to test a service of mine that is called GetUsersForRole. It takes in a simple string and is passes this off to my RoleRepository to deal with NHibernate and get a collection of Roles with the passed in string for its RoleName. To do this, I have a Find function on my RoleRepository that calls this code:

ICriteria crit = rb.unitOfWork.Session.CreateCriteria(typeof(Entity));
crit.SetCacheable(false);
foreach (object[] criteriaItem in criteria)
{
   crit.Add(Expression.Eq((string)criteriaItem[0], criteriaItem[1]));
}

return crit.List().Cast<Entity>();

So the code above will return a list of roles and within that, there is a property defined as Iesi.Collections.ISet called Users. If a given role has Users tied to it (through a many-to-many), this property is populated.

From here, I deal with the result of this Find function and get the first Role, then I use ValueInjector to map the role.Users property to an IEnumerable set. This works 100%. Here is the code that does this:

var role = _roleRepo.Find(new List<object[]>()
                               {
                                   new object[] {"Name", roleName}
                               }).FirstOrDefault();

if (role == null)
    return null;

MapperFactory.ClearMappers();
MapperFactory.AddMapper(new ISetToIEnumerable<User, UserDTO>());

var users = Mapper.Map<Iesi.Collections.ISet, IEnumerable<UserDTO>>(role.Users);

return users;

I'm using value Injector's Automapper Simulation class to deal with set mappings. This can be found here. I had to make a special Mapper to work with the Iesi.Collections.ISet to IEnumerable mappings:

public class ISetToIEnumerable<TSource, TTarget> : TypeMapper<Iesi.Collections.ISet, IEnumerable<TTarget>>
{
    public override IEnumerable<TTarget> Map(Iesi.Collections.ISet source, IEnumerable<TTarget> target)
    {
        base.Map(source, target);

        List<TTarget> entities = new List<TTarget>();
        foreach (var entity in source)
        {
            entities.Add(Mapper.Map<TSource, TTarget>((TSource)entity));
        }
        target = entities.AsEnumerable();
        return target;
    }
}

Again, this works 100%. In the ISetToIEnumerable mapper class, the argument source comes across as Iesi.Collections.ISet {NHibernate.Collection.PersistantSet}. This is where things mess up when trying to unit test this.

I'm trying to test a successful run with this Unit Test:

    [Test]
    public void GetUsersForRole_success()
    {
        // Arrange
        var roles = new List<Role>();
        var role = new Role()
                       {
                           Name = "role1",
                           Users = {new User() {Username = "user1"}, new User() {Username = "user2"}}
                       };
        roles.Add(role);

        _mockRoleRepository.Setup(m => m.Find(It.IsAny<IList<object[]>>())).Returns(roles);

        var service = GetDefaultService();

        // Act
        var users = service.GetUsersForRole("role1");

        Assert.That(users.Count() == 2);
    }

When I debug this and step into the service.GetUsersForRole("role1") call, I get my mocked data back from my mockRoleRepository. The issue here is that my role.Users property is coming back types as Iesi.Collections.HashedSet (this is how it is instantiated in my Entity Constructor for both testing and real runs with NHibernate). Now this becomes a major issue in my ISetToIEnumerable class. My source is coming across typed as Iesi.Collections.HashedSet.

I know that I will not be able to type my mock using the NHibernate.Collection.PersistantSet because of the lack of an NHibernate session instance. Does anyone have any thoughts on what is going on here and how I might be able to replicate what NHibernate is doing to my Iesi.Collections.ISet in my Arrangement of my Mock data?

有帮助吗?

解决方案

If I understand you correct, you have an ISet<T> in your domain model? Why don't you use this as your source in your mapper? Why the non generic interface?

Another alternative, is that you have a general interface for both the generic and non generic interface like IEnumerable as your source in your mapper.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top