2015-05-18 5 views
1

Так что я пытаюсь использовать Autofac Automocking в ASP.NET MVC 5, но по какой-то причине я не могу заставить его работать.Autofac Automocking в ASP.NET MVC

Вот тест до сих пор:

using (var mock = AutoMock.GetLoose()) 
{ 
      const string mainUserID = "MainUserID"; 
      const string otherUserID = "OtherUserID"; 
      ApplicationUser user = new ApplicationUser() 
      { 
       Id = mainUserID, 
       UserName = "TestUser" 
      }; 

      var dataProvider = mock.Mock<IDataProtectionProvider>(); 
      dataProvider.DefaultValue = DefaultValue.Mock; 

      var userManagerMock = mock.Mock<ApplicationUserManager>(); 
} 

Тест терпит неудачу, когда насмешливый ApplicationUserManager. Ошибка заключается в следующем:

Result StackTrace: 
at Autofac.Extras.Moq.AutoMock.Mock[T](Parameter[] parameters) 
at AwenterWeb_NUnit.AccountControllerTest.<Deactivate_User>d__0.MoveNext() in C:\Users\Fabis\Documents\Docs\Kvalifikācijas darbs 2015\AwenterWeb\AwenterWeb-NUnit\AccountControllerTest.cs:line 51 
at NUnit.Framework.AsyncInvocationRegion.AsyncTaskInvocationRegion.WaitForPendingOperationsToComplete(Object invocationResult) 
at NUnit.Core.NUnitAsyncTestMethod.RunTestMethod() 
Result Message: System.InvalidCastException : Unable to cast object of type 'AwenterWeb.ApplicationUserManager' to type 'Moq.IMocked`1[AwenterWeb.ApplicationUserManager]'. 

То же самое происходит при попытке automock в ApplicationDbContext и имеет очень простой конструктор, так что не должно быть даже какие-либо вопросы с ним. Я новичок в Mocking - что мне делать в этом сценарии?

Edit: Также вид несвязанный вопрос, может быть, вы, ребята, знаете, - я заметил, что при создании Moq для DbSet, используя список, созданный ранее в тесте, я должен сделать это:

var dbSetMock = new Mock<IDbSet<DbEntity>>(); 
      dbSetMock.Setup(m => m.Provider).Returns(data.Provider); 
      dbSetMock.Setup(m => m.Expression).Returns(data.Expression); 
      dbSetMock.Setup(m => m.ElementType).Returns(data.ElementType); 
      dbSetMock.Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator()); 

Кажется действительно неинтуитивным. Есть ли способ сказать макету, чтобы взять список? Так что-то вроде:

dbSetMock.Setup(m => m).Returns(data); 

или любым другим способом, чтобы создать DbSet Moq из существующего списка быстро, без необходимости писать эти 4 дополнительные линии?

+0

Почему вы создаете макет на конкретный тип? Вы хотите издеваться над 'ApplicationUserManager'? или получить конкретный пример, чтобы проверить его? –

+0

Метод, который я тестирую, использует UserManager для поиска пользователя, обновления пользователя и т. Д. (Identity 2.0), поэтому я пытаюсь его высмеять. – Fabis

ответ

1

Если посмотреть на Ligne 73 MoqRegistrationHandler.cs вы можете увидеть, что только интерфейс moqable с помощью Autofac.Extras.Moq

var typedService = service as TypedService; 
if (typedService == null || 
    !typedService.ServiceType.IsInterface || 
    typedService.ServiceType.IsGenericType && typedService.ServiceType.GetGenericTypeDefinition() == typeof(IEnumerable<>) || 
    typedService.ServiceType.IsArray || 
    typeof(IStartable).IsAssignableFrom(typedService.ServiceType)) 
    return Enumerable.Empty<IComponentRegistration>(); 


var rb = RegistrationBuilder.ForDelegate((c, p) => CreateMock(c, typedService)) 
    .As(service) 
    .InstancePerLifetimeScope(); 

Вы можете изменить код, но он может быть довольно трудно сделать это работает с меньшей зависимостью от параметра.

Могут ли быть изменены зависимости для использования интерфейса вместо конкретного класса? если это невозможно и/или если это не имеет смысла, вы можете использовать MockRepository, чтобы создать свой компонент без параметра без параметров, а затем ввести его в класс AutoMock.

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var mock = AutoMock.GetLoose()) 
     { 
      /// configure your non interface component with constructor parameters 
      /// if foo need more complex parameters you can get them 
      /// using mock.Mock<T>().Object 
      var fooMock = mock.MockRepository.Create<Foo>((String)null); 
      fooMock.SetupGet(f => f.Value).Returns("test"); 

      // insert your instance into the container 
      mock.Provide<Foo>(fooMock.Object); 


      var bar = mock.Create<Bar>(); 
      Console.WriteLine(bar.GetValue()); 
     } 
    } 
} 

public class Foo 
{ 
    public Foo(String value) 
    { 
     this._value = value; 
    } 

    private readonly String _value; 

    public virtual String Value 
    { 
     get 
     { 
      return this._value; 
     } 
    } 
} 

public interface IBar 
{ 
    String GetValue(); 
} 
public class Bar : IBar 
{ 
    public Bar(Foo foo) 
    { 
     this._foo = foo; 
    } 

    private readonly Foo _foo; 

    public String GetValue() 
    { 
     return this._foo.Value; 
    } 
} 

Это не идеальное решение, но без большого рефакторинга проекта Autofac.Extras.Moq я не вижу простой способ сделать это.

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

  • Нет связанных вопросов^_^