나는 Mark Seeman의 article on auto-mocking을 읽었으며 그 기사를 기반으로 재사용 가능한 윈저 컨테이너를 작성하고 있습니다.SUT Automocking
은 (기본적으로 직접 복사) 마크의 기사
의 내 구현의 주요 작업은 AutoMoqResolver
클래스에서 이루어집니다.
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 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;
}
}
AutoMoqResolver
는 IWindsorInstaller
인터페이스의 다음과 같은 구현을 사용하여 컨테이너에 추가됩니다 클래스가 인터페이스에 대한 종속성이있을 때마다이 모의를 제공합니다 인스톨러는 단위 테스트에서 인터페이스 의존성을 자동으로 제공합니다.
public class AutoMockContainer<T> : WindsorContainer
{
public AutoMockContainer()
{
// simply run the auto-mock installer
this.Install(new AutoMockInstaller<T>());
}
}
슈퍼!
이 테스트를 거쳤으며 필자의 의존성이 기꺼이 자동으로 조롱을 받아 일부 실제 코드에 적용되었습니다. 이것은 내가 클래스를 테스트 할 때 따라야하는 패턴 때문에 해결책이 도움이되지 않는다는 것을 깨달았을 때입니다. 내 특정 문제는 SUT 자체에서 자동 테스트를 통해 SUT의 한 메서드가 다른 메서드에서 호출되는지 확인할 수 있기를 원합니다. 필요
내 코드는 내가 예를 통해 자신을 설명 할 것이다
을 테스트 할 수 있습니다. 내가 MVC 코드를 개발하고 나는 다음과 같은 일반적인 패턴을 사용하여 눈에 거슬리지 AJAX를 지원하고 있습니다 :
public Class ExampleController : Controller
{
private IService service;
public ExampleController(IService service)
{
this.service = service;
}
public PartialViewResult DoSomethingWithAjax()
{
this.PerformTask();
return this.PartialView();
}
public RedirectToRouteResult DoSomethingWithoutAjax()
{
this.PerformTask();
return this.RedirectToAction("SomeAction");
}
protected virtual void PerformTask()
{
// do something here
}
}
내 테스트 패턴을
그래서 PerformTask()
방법은 DoSomethingWithAjax()
또는 DoSomethingWithoutAjax()
에서 호출되었는지 확인하기 위하여, I 이 같은 새로운 TestableExampleController
클래스를 정의 :
public class TestableExampleController : ExampleController
{
public TestableExampleController(IService service) : base(service)
{
}
public virtual void PerfomTaskPublic()
{
base.PerfomTask();
}
protected override void PerformTask()
{
this.PerformTaskPublic();
}
}
내가 다음 TES 그래서 내 SUT로 TestableExampleController
을 사용할 수 있습니다 t은 통과 할 것이다 :
[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());
}
내 문제
이처럼 내 AutoMockContainer
클래스를 사용하는이 테스트를 리팩토링은 작동하지 않습니다
[TestMethod]
public void DoSomethingAjax_Calls_PerformTask()
{
//// Arrange
// create a container
var container = new AutoMockContainer<TestableExampleController>();
// resolve a mock SUT using the container
var controllerMock = container.Resolve<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());
}
시험은 Mock<TestableExampleController>
의 인스턴스를 생성 실패 매개 변수없는 생성자를 찾을 수 없기 때문입니다.
클래스의 프록시를 인스턴스화 할 수 없습니다 : MyNamespace.TestableExampleController. 매개 변수없는 생성자를 찾을 수 없습니다. 매개 변수 이름 : constructorArguments 이상적으로
내가 자동으로 구성 요소에 대한 모의 제공하기 위해 컨테이너에 등록 할 수있는 래퍼 클래스 구현하고자하는
내 제안 솔루션 :
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; }
}
}
을 나는 다음 테스트를 통과 할 수 있기를 바랍니다.
[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());
}
나는 이것을 달성하는 방법에 대해 꽤 고개를 숙일 수가 없으며 새로운 ISubDependencyResolver 구현을 사용하여 대부분의 시간을 보냈지만이 기능을 사용할 수는 없습니다.
제 질문은 명확하고 답변은 실제로 비교적 간단합니다.
: http://stackoverflow.com/questions/11958110/technique-for-using-autofixture-to-integration-test-an-application -using-castle AutoFixture를 사용하는 것으로 괜찮 으면 autofixture 태그를 추가 할 수 있습니다. – TrueWill
안녕하세요 닉, Rhino Mock을 사용하기 위해 similair를 사용했습니다. 여기에는 코드가 없지만 Lazy Component Loader를 사용했다는 것을 상기합니다. 이렇게하면 요청 된 모든 종속성을 등록 할 수 있습니다. 따라서 하위 종속 결정자 대신에 이것이 효과가 있는지 알 수 있습니다. – Marwijn