2015-10-09 4 views
2

У меня есть некоторые проблемы с насмешкой локальной переменной в методе моего класса.Смещение локальной переменной в вызывающем методе

Я пытаюсь высмеять мой класс Worker, но он вызывает метод, который возвращает значение null, а моя контекстная переменная становится нулевой. Таким образом, я получаю исключение, когда пытаюсь получить свойство Name.

Как заставить CreateWorkerContext() вернуть значения? Может быть, есть способ издеваться над локальной переменной (context)?

Спасибо!

Мой код будет более подробно рассказать об этой проблеме:

namespace Moq 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var workerMock = new Mock<Worker>(); 
      workerMock.Object.GetContextName(); 
     } 
    } 

    public class Worker 
    { 
     public string GetContextName() 
     { 
      // something happens and context does not create (imitated situation) 
      WorkerContext context = CreateWorkerContext(); 

      // exception because _context is null 
      return context.Name; 
     } 

     private WorkerContext CreateWorkerContext() 
     { 
      // imitate that context is not created 
      return null; 
     } 
    } 

    public class WorkerContext 
    { 
     public string Name { get; set; } 
    } 
} 
+1

Вам необходимо полностью распаковать или изменить «WorkerContext CreateWorkerContext()». Возможно, нужно вставить конструктор 'IWorkerContextFactory' в конструктор' Worker'. – CodeCaster

+0

1 для завода. Или сделайте инъекцию «IWorkerContex». – rbm

+0

Таким образом, нет никакого способа делать издевательство без изменения исходного кода. Sad – yurart

ответ

5

Несколько вещей спорны здесь.

Первый, - но это только мое мнение - вы должны избегать частичного насмешливый (частичный насмешливые = издеваться абстрактный класс, который не реализует интерфейс, и, следовательно, сохраняет первоначальную реализацию методов, которые weren - насмешливо. Лучше всего было бы иметь интерфейс IWorker, который Worker будет imlepement.

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

Третьего - Я бы Ввожу WorkerContext. Если вы не можете вводить его, потому что вам нужно параметризуем его прийти .ctor аргументы, затем впрыснуть WorkerContextFactory, который позволит издеваться создание и параметризацию ваших WorkerContext

3

динамических макетов библиотек как Moq, вообще говоря, не магия. They can only replace the behaviour that you yourself could replace with code.

В этом конкретном примере Moq не может заменить CreateWorkerContext, потому что это частный метод.

Один из вариантов, чтобы сделать его virtual:

public class Worker 
{ 
    public string GetContextName() 
    { 
     WorkerContext context = CreateWorkerContext(); 
     return context.Name; 
    } 

    public virtual WorkerContext CreateWorkerContext() 
    { 
     return new WorkerContext(); 
    } 
} 

Другим вариантом было бы заменить метод CreateWorkerContext с Strategy:

public class Worker 
{ 
    private readonly IWorkerContextFactory factory; 

    public Worker(IWorkerContextFactory factory) 
    { 
     if (factory == null) 
      throw new ArgumentNullException(nameof(factory)); 

     this.factory = factory; 
    } 

    public string GetContextName() 
    { 
     WorkerContext context = this.factory.Create(); 
     return context.Name; 
    } 
} 

Оба этих варианта позволит Moq моделировать желаемое поведение.

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