2009-11-24 3 views
2

у меня есть что-то вроде этогокак издеваются container.Resolve <Type>()

public class HomeController 
{ 
    public ActionResult Index() 
    { 
     var x = Container.Resolve<IOrganisationService>(); 
    } 
} 

когда модульное тестирование я получаю нулевой ссылочный исключение, когда контейнер пытается разрешить
кто-нибудь знает, как сделать, чтобы издеваться контейнер. Разрешить() ?

+1

Что вы используете для контейнера? – Lazarus

+0

Я использую Виндзорский замок – Omu

ответ

0

Я сделал это, это так:

//code inside the setup method 
var c = new Moq.Mock<IWindsorContainer>(); 
var l = new Moq.Mock<ILookupService>(); 
l.Setup(o => o.GetItems(It.IsAny<String>())).Returns(new List<LookupItem>()); 
c.Setup(o => o.Resolve<ILookupService>()).Returns(l.Object); 
LocatorConfigurator.SetContainer(c.Object); 
+3

Я бы старался избегать этого и использовать то, что показал Марк и Кент выше. –

4

Вопрос в том, почему вы решаете его таким образом? Если вместо этого зависимость инъекции, то вы можете легко насмехаться:

public class HomeController 
{ 
    private readonly IOrganisationService organisationService; 

    public HomeController(IOrganisationService organisationService) 
    { 
     this.organisationService = organisationService; 
    } 

    public ActionResult Index() 
    { 
     var x = this.organisationService; 
    } 
} 
+0

Нет, это не так, я просто попытался упростить, на самом деле мне это нужно – Omu

+0

@Omu: зачем вам это нужно? –

6

Вы не можете, потому что метод Resolve в вопросе является статическим методом. Это одна из многих причин, по которым статические типы считаются злом, когда дело доходит до модульного тестирования (и, следовательно, для общей компоновки кода).

Вы, кажется, применяете шаблон (анти), известный как Service Locator, и вы в настоящее время испытываете одну из многих проблем, связанных с ним.

Лучшим решением было бы использовать Constructor Injection так:

public class HomeController 
{ 
    private readonly IOrganisationService organisationService; 

    public HomeController(IOrganisationService organisationService) 
    { 
     if (organisationService == null) 
     { 
      throw new ArgumentNullException("organisationService"); 
     } 

     this.organisationService = organisationService; 
    } 

    public ActionResult Index() 
    { 
     var x = this.organisationService; 
     // return result... 
    } 
} 

Теперь вы можете позволить DI Контейнер выбора разрешения экземпляра HomeController извне. Это гораздо более гибкое решение.

+0

Почему downvote? –

0

Некоторые контейнеры (например, Виндзор) имеют контейнер, который наследуется от интерфейса. Если вы используете это, то это неявно макет. Если вы создали статический метод, на который вы можете вызвать разрешение, то, как указано выше, его нельзя высмеять, не рекомендуется. Если ваш контейнер не наследуется от интерфейса (или используемого вами шаблона локатора службы), он полагается на статический метод, а затем меняет реализацию, поэтому он основан на экземпляре и поэтому макет.

Однако, я согласен с сообщениями выше. Вам не нужно действительно ссылаться на ваш контейнер из вашего кода. Это связывает ваше приложение с контейнером, из которого вы пытаетесь избежать, используя контейнер.

Смежные вопросы