Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自动模拟SUT_C#_Unit Testing_Castle Windsor_Autofixture_Automocking - Fatal编程技术网

C# 自动模拟SUT

C# 自动模拟SUT,c#,unit-testing,castle-windsor,autofixture,automocking,C#,Unit Testing,Castle Windsor,Autofixture,Automocking,我已经阅读了MarkSeeman的文章,现在我正在根据这篇文章编写一个可重用的windsor容器 我对马克文章的实施(基本上是直接抄袭) 主要工作是在AutoMoqResolver类中完成的。这将在类依赖于接口时提供模拟: public class AutoMoqResolver : ISubDependencyResolver { private readonly IKernel kernel; public AutoMoqResolver(IKernel kernel)

我已经阅读了MarkSeeman的文章,现在我正在根据这篇文章编写一个可重用的windsor容器

我对马克文章的实施(基本上是直接抄袭)

主要工作是在
AutoMoqResolver
类中完成的。这将在类依赖于接口时提供模拟:

public class AutoMoqResolver : ISubDependencyResolver
{
    private readonly IKernel kernel;

    public AutoMoqResolver(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public bool CanResolve(
        CreationContext context,
        ISubDependencyResolver contextHandlerResolver,
        ComponentModel model,
        DependencyModel dependency)
    {
        return dependency.TargetType.IsInterface;
    }

    public object Resolve(
        CreationContext context,
        ISubDependencyResolver contextHandlerResolver,
        ComponentModel model,
        DependencyModel dependency)
    {
        var mockType = typeof(Mock<>).MakeGenericType(dependency.TargetType);
        return ((Mock)this.kernel.Resolve(mockType)).Object;
    }
}
public class AutoMockInstaller<T> : IWindsorInstaller
{
    public void Install(
        IWindsorContainer container,
        IConfigurationStore store)
    {
        container.Kernel.Resolver.AddSubResolver(
            new AutoMoqResolver(container.Kernel));

        container.Register(Component.For(typeof(Mock<>)));

        container.Register(Classes
            .FromAssemblyContaining<T>()
            .Pick()
            .WithServiceSelf()
            .LifestyleTransient());
    }
}
然后,我的容器只需运行安装程序,就可以为单元测试中的任何接口依赖项自动提供模拟:

public class AutoMockContainer<T> : WindsorContainer
{
    public AutoMockContainer()
    {
        // simply run the auto-mock installer
        this.Install(new AutoMockInstaller<T>());
    }
}
我的测试模式

因此,为了验证
PerformTask()
方法是从
DoSomethingWithAjax()
DoSomethingWithAjax()
调用的,我定义了一个新的
TestableExampleController
类,如下所示:

public class TestableExampleController : ExampleController
{
    public TestableExampleController(IService service) : base(service)
    {
    }

    public virtual void PerfomTaskPublic()
    {
        base.PerfomTask();
    }

    protected override void PerformTask()
    {
        this.PerformTaskPublic();
    }
}
然后,我可以使用
TestableExampleController
作为我的SUT,以便通过以下测试:

[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
    //// Arrange
    // create a mock TestableExampleController
    var controllerMock = new Mock<TestableExampleController>();
    controllerMock.CallBase = true;

    // use the mock controller as the SUT
    var sut = controllerMock.Object;

    //// Act
    sut.DoSomethingAjax();

    //// Assert
    controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
[TestMethod]
public void Run_Calls_DoSomethingProtected()
{
    //// Arrange
    // AutoMoqCustomization allows AutoFixture to 
    // be used an an auto-mocking container
    var fixture = new Fixture().Customize(new AutoMoqCustomization());

    // simply ask the fixture to create a mock
    var sutMock = fixture.Create<Mock<TestableDummySystem>>();

    //// Act
    // exercise the mock object
    sutMock.Object.Run();

    //// Assert
    // this verification passes!
    sutMock.Verify(x => x.DoSomethingProtectedPublic());
}
测试无法创建
Mock
的实例,因为它找不到无参数构造函数

无法实例化类MyNamespace.TestableExampleController的代理。 找不到无参数构造函数。 参数名称:构造函数参数

我提出的解决方案

理想情况下,我希望实现一个包装器类,该类可以注册到容器中,以自动为任何组件提供模拟:

public class ComponentWrapper<T> where T : class
{
    public ComponentWrapper(Mock<T> componentMock)
    {
        componentMock.CallBase = true;
        this.ComponentMock = componentMock;
    }

    public Mock<T> ComponentMock { get; private set; }

    public T Component
    {
        get { return this.ComponentMock.Object;  }
    }
}
公共类组件包装器,其中T:class
{
公共组件包装器(Mock componentMock)
{
componentMock.CallBase=true;
this.ComponentMock=ComponentMock;
}
公共模拟组件Mock{get;private set;}
公共T组件
{
获取{返回this.ComponentMock.Object;}
}
}
我希望能够编写以下通过的测试:

[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
    //// Arrange
    // create a container
    var container = new AutoMockContainer<TestableExampleController>();

    // resolve a ComponentWrapper using the container
    var wrapper = container.Resolve<ComponentWrapper<TestableExampleController>>();

    //// Act
    // call a method using the component
    wrapper.Component.DoSomethingAjax();

    //// Assert
    // verify a method call using the mock
    wrapper.ComponentMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
////安排
//创建一个容器
var container=new AutoMockContainer();
//使用容器解析ComponentWrapper
var wrapper=container.Resolve();
////表演
//使用组件调用方法
wrapper.Component.DoSomethingAjax();
////断言
//使用mock验证方法调用
wrapper.ComponentMock.Verify(x=>x.PerformTaskPublic(),Times.Once());
}
我无法完全理解如何实现这一点,我花了一天的大部分时间来摆弄新的ISubDependencyResolver实现,但我就是无法实现这一点


希望我的问题很清楚,答案其实也相对简单?

事实证明,AutoFixture.AutoMoq能做我想做的事情,所以感谢TrueWill为我指明了正确的方向

以下简单测试将通过:

[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
    //// Arrange
    // create a mock TestableExampleController
    var controllerMock = new Mock<TestableExampleController>();
    controllerMock.CallBase = true;

    // use the mock controller as the SUT
    var sut = controllerMock.Object;

    //// Act
    sut.DoSomethingAjax();

    //// Assert
    controllerMock.Verify(x => x.PerformTaskPublic(), Times.Once());
}
[TestMethod]
public void Run_Calls_DoSomethingProtected()
{
    //// Arrange
    // AutoMoqCustomization allows AutoFixture to 
    // be used an an auto-mocking container
    var fixture = new Fixture().Customize(new AutoMoqCustomization());

    // simply ask the fixture to create a mock
    var sutMock = fixture.Create<Mock<TestableDummySystem>>();

    //// Act
    // exercise the mock object
    sutMock.Object.Run();

    //// Assert
    // this verification passes!
    sutMock.Verify(x => x.DoSomethingProtectedPublic());
}
[TestMethod]
public void Run_Calls_DoSomethingProtected()
{
////安排
//AutoMoqCustomization允许AutoFixture
//用于自动模拟容器
var fixture=new fixture().Customize(new AutoMoqCustomization());
//只需让夹具创建一个模拟
var sutMock=fixture.Create();
////表演
//练习模拟对象
sutMock.Object.Run();
////断言
//这个验证通过了!
验证(x=>x.DoSomethingProtectedPublic());
}

这可能会有所帮助:如果您对使用AutoFixture没有问题,您可能需要添加AutoFixture标记。你好,尼克,我做了一些与Rhino Mock类似的操作。我没有这里的代码,但我记得我使用了一个懒惰的组件加载程序。这样,您可以在请求任何依赖项时注册它们。因此,您可以查看这是否适用于您,而不是子依赖解析程序。