Sparky의 도구 팁: Moq.AutoMock

아마도 .NET 클래스를 단위 테스트 가능하게 만드는 가장 중요한 것은 일반적으로 생성자 주입을 통해 dependency injection (주입 interfaces, not implementations )입니다.

모의 라이브러리를 사용하면 "모의"인터페이스 구현을 쉽게 생성하고 인터페이스가 예상대로 사용되었는지 확인할 수 있습니다. Moq은 가장 인기 있는 .NET 모의 라이브러리입니다.

If you're using Moq, you may be interested in my NuGet packages. They provide an alternative to "It.IsAny" and "It.Is" syntax that I think is easier to write and read, and fluent assertions for verifications.



....인터페이스 손실

Moq.AutoMock NuGet package은 Moq용 "자동 조롱"컨테이너를 제공합니다.

AutoMocker.CreateInstance는 지정된 유형의 새 인스턴스를 만들고 모든 생성자 인터페이스 매개변수에 대한 Mock을 자동으로 생성합니다. (클래스에는 모든 매개변수가 인터페이스인 생성자가 있어야 함):

AutoMocker 없이:

var mockReader = new Mock<IReader>();
var mockFormatter = new Mock<IFormatter>();
var mockLogger = new Mock<ILogger>();
var foo = new Foo(
    mockReader.Object, mockFormatter.Object, mockLogger.Object);


AutoMocker 사용:

var autoMocker = new AutoMocker();
var foo = autoMocker.CreateInstance<Foo>();


.Setup 또는 .Verify 모의 동작을 수행하려면 AutoMocker의 "GetMock"메서드를 통해 자동 생성된 모의를 얻을 수 있습니다.

autoMocker.GetMock<IFormatter>.Setup(x =>
    x.Format(It.IsAny<decimal>()).Returns(x => x.ToString("###.00"));


일반적으로 사용되는 일부 인터페이스에 대해 "행복한 경로"동작을 설정하는 프로젝트에 대한 사용자 지정 AutoMocker 하위 클래스를 만드는 것이 유리할 수 있습니다.

public class CustomAutoMocker : AutoMocker
{
    // constructor
    public CustomAutoMocker()
    {
        // Set up commonly used interfaces
        Mock<IFormatter> mockFormatter = GetMock<IFormatter>();
        //mockFormatter.Setup(x => ...
    }
}



    var autoMocker = new CustomAutoMocker();
    var foo autoMocker.CreateInstance<Foo>();
    // following tests will use Setups defined in the CustomAutoMocker


사용자 지정 AutoMocker 하위 클래스는 특정 유형의 인스턴스가 생성될 때 추가 논리를 수행하기 위해 CreateInstance 메서드를 재정의할 수도 있습니다. 예를 들어, 내가 작업하는 ApiController를 사용하는 프로젝트에서(원래 단위 테스트를 염두에 두고 작성되지 않은) ApiController 인스턴스의 구성을 감지하고 자동으로 .Request 및 .User 속성을 설정합니다.

public class CustomAutoMocker : AutoMocker
...
public new T CreateInstance<T>() where T : class
{
    T instance = base.CreateInstance<T>();

    var apiController = instance as ApiController;
    if (apiController != null)
    {
        // Set up ApiController's Request and User 
        apiController.Request = new HttpRequestMessage();
        apiController.Request.SetConfiguration(new HttpConfiguration());
        apiController.User = BuildClaimsPrincipal();
    }

    return instance;
}

private ClaimsPrincipal BuildClaimsPrincipal()
{
    // (code to build ClaimsPrincipal and
    // assign it to Thread.CurrentPrincipal)
}



Mock.AutoMock 및 사용자 지정 AutoMocker 하위 클래스는 단위 테스트에서 작성해야 하는 반복적이고 지루한 모의 설정 코드의 양을 크게 줄였습니다.

Moq을 사용하신다면 적극 추천합니다.

좋은 웹페이지 즐겨찾기