Avatar billede softspot Forsker
13. februar 2012 - 16:06 Der er 4 kommentarer og
1 løsning

Mocking IDependencyResolver med Moq (ASP.NET MVC 3)

Jeg vil gerne teste en factoryklasse som benytter DependencyResolver til at oprette objektet.

Jeg har flg. struktur i min factory:

public class PersonFactory : IPersonFactory
{
    private IDependencyResolver _dr;
    private readonly IPersonRepository _repository;

    public PersonFactory(IPersonRepository repository)
    {
        _repository = repository;
    }

    public IDependencyResolver Resolver
    {
        get { return _dr ?? DependencyResolver.Current; }
        set { _dr = value; }
    }

    public IPerson CreateInstance()
    {
        return Resolver.GetService<IPerson>();
    }

    public IPerson GetByEmail(string email)
    {
        IPerson person = CreateInstance();
        person.Email = email;
        _repository.Get(person);
        return person;
    }
}


Nu vil jeg gerne teste min factory og det forsøger at gøre således:

[TestMethod()]
public void GetByEmail()
{
    // Arrange
    var mock = new Mock<IPersonRepository>();
    mock.Setup(r => r.Get(It.IsAny<IPerson>()));

    var mockObj = new Mock<IPerson>();

    var mockResolver = new Mock<IDependencyResolver>();
    mockResolver.Setup(m => m.GetService<IPerson>()).Returns(mockObj.Object);

    PersonFactory target = new PersonFactory(mock.Object);
    target.Resolver = mockResolver.Object;

    string email = "test@dummy.dk";

    // Act
    IPerson actual = target.GetByEmail(email);

    // Assert
    Assert.IsInstanceOfType(actual, typeof(IProfile));
}


Problemet er pt. at linjen med fed i testmetoden ikke fungerer. Jeg får en runtimefejl

Expression references a method that does not belong to the mocked object: m => m.GetService<IPerson>()


Spørgsmålet er så hvad jeg skal skrive i stedet for, for at få det til at fungere?
Avatar billede janus_007 Nybegynder
13. februar 2012 - 20:53 #1
hmmm er det ikke noget med DependencyResolver.Current?

mockResolver.Setup(d => d.Current);

eller
mockResolver.Setup(m => m.Current.GetService<IPerson>()).Returns(mockObj.Object);

Har du overvejet at bruge at DI-framework ifb. med Moq, det gør jeg og oplever ingen problemer :)
Avatar billede softspot Forsker
13. februar 2012 - 21:11 #2
Jeg er ikke nået så langt i min udvilking af brugen af DI-frameworks, at jeg er begyndt at bruge dem til tests (babysteps you know ;-)). Jeg bruger Ninject i selve systemet (som du måske kan huske at have hjulpet mig igang med tidligere) og det fungerer rigtig godt - det er jeg rigtig glad for!

Anyway! Jeg har imidlertid prøvet at mocke den ikke generiske version af GetService på IDependencyResolver og så fungerede det. Min testkode kommer så til at se således ud:

[TestMethod()]
public void GetByEmail()
{
    // Arrange
    var mock = new Mock<IPersonRepository>();
    mock.Setup(r => r.Get(It.IsAny<IPerson>()));

    var mockObj = new Mock<IPerson>();

    var mockResolver = new Mock<IDependencyResolver>();
    mockResolver.Setup(m => m.GetService(It.IsAny<Type>())).Returns(mockObj.Object);
    DependencyResolver.SetResolver(mockResolver.Object);

    IPersonFactory target = new PersonFactory(mock.Object);

    string email = "test@dummy.dk";

    // Act
    IPerson actual = target.GetByEmail(email);

    // Assert
    Assert.IsInstanceOfType(actual, typeof(IProfile));
}


Desuden kan jeg, med ændringen i min testkode, også ændre min Factory til at se således ud (altså fjerne Resolver-egenskaben, da jeg stopper min mock-resolver ned i halsen på MVC's Resolver  og gør brug af den i min factory i stedet):

public class PersonFactory : IPersonFactory
{
    private readonly IPersonRepository _repository;

    public PersonFactory(IPersonRepository repository)
    {
        _repository = repository;
    }

    public IPerson CreateInstance()
    {
        return DependencyResolver.Current.GetService<IPerson>();
    }

    public IPerson GetByEmail(string email)
    {
        IPerson person = CreateInstance();
        person.Email = email;
        _repository.Get(person);
        return person;
    }
}
Avatar billede softspot Forsker
14. februar 2012 - 08:19 #3
Tak for hjælpen, janus_007.

Smid et svar, så du kan få point for din tid.
Avatar billede softspot Forsker
01. marts 2012 - 10:34 #4
Janus, vil du have point?
Avatar billede softspot Forsker
04. marts 2012 - 12:03 #5
OK, så hiver jeg dem tilbage...

Tak for hjælpen.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester